mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-30 07:51:28 +00:00
- Backend update from Raze
This commit is contained in:
parent
55ce0510c2
commit
ba146ed5e5
43 changed files with 473 additions and 168 deletions
|
@ -189,8 +189,9 @@ DEFINE_ACTION_FUNCTION_NATIVE(DShape2D, PushTriangle, Shape2D_PushTriangle)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int F2DDrawer::AddCommand(const RenderCommand *data)
|
||||
int F2DDrawer::AddCommand(RenderCommand *data)
|
||||
{
|
||||
data->mScreenFade = screenFade;
|
||||
if (mData.Size() > 0 && data->isCompatible(mData.Last()))
|
||||
{
|
||||
// Merge with the last command.
|
||||
|
@ -738,12 +739,12 @@ void F2DDrawer::AddPoly(FGameTexture *texture, FVector2 *points, int npoints,
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void F2DDrawer::AddPoly(FGameTexture* img, FVector4* vt, size_t vtcount, unsigned int* ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, int clipx1, int clipy1, int clipx2, int clipy2)
|
||||
void F2DDrawer::AddPoly(FGameTexture* img, FVector4* vt, size_t vtcount, const unsigned int* ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, int clipx1, int clipy1, int clipx2, int clipy2)
|
||||
{
|
||||
RenderCommand dg;
|
||||
int method = 0;
|
||||
|
||||
if (!img->isValid()) return;
|
||||
if (!img || !img->isValid()) return;
|
||||
|
||||
dg.mType = DrawTypeTriangles;
|
||||
if (clipx1 > 0 || clipy1 > 0 || clipx2 < GetWidth() - 1 || clipy2 < GetHeight() - 1)
|
||||
|
@ -769,14 +770,28 @@ void F2DDrawer::AddPoly(FGameTexture* img, FVector4* vt, size_t vtcount, unsigne
|
|||
Set(ptr, vt[i].X, vt[i].Y, 0.f, vt[i].Z, vt[i].W, color);
|
||||
ptr++;
|
||||
}
|
||||
|
||||
dg.mIndexIndex = mIndices.Size();
|
||||
mIndices.Reserve(idxcount);
|
||||
for (size_t i = 0; i < idxcount; i++)
|
||||
|
||||
if (idxcount > 0)
|
||||
{
|
||||
mIndices[dg.mIndexIndex + i] = ind[i] + dg.mVertIndex;
|
||||
mIndices.Reserve(idxcount);
|
||||
for (size_t i = 0; i < idxcount; i++)
|
||||
{
|
||||
mIndices[dg.mIndexIndex + i] = ind[i] + dg.mVertIndex;
|
||||
}
|
||||
dg.mIndexCount = (int)idxcount;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we have no index buffer, treat this as an unindexed list of triangles.
|
||||
mIndices.Reserve(vtcount);
|
||||
for (size_t i = 0; i < vtcount; i++)
|
||||
{
|
||||
mIndices[dg.mIndexIndex + i] = i + dg.mVertIndex;
|
||||
}
|
||||
dg.mIndexCount = (int)vtcount;
|
||||
|
||||
}
|
||||
dg.mIndexCount = (int)idxcount;
|
||||
AddCommand(&dg);
|
||||
}
|
||||
|
||||
|
@ -941,6 +956,7 @@ void F2DDrawer::AddColorOnlyQuad(int x1, int y1, int w, int h, PalEntry color, F
|
|||
{
|
||||
// Only needed by Raze's fullscreen blends because they are being calculated late when half of the 2D content has already been submitted,
|
||||
// This ensures they are below the HUD, not above it.
|
||||
dg.mScreenFade = screenFade;
|
||||
mData.Insert(0, dg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,6 +118,7 @@ public:
|
|||
ETexMode mDrawMode;
|
||||
uint8_t mLightLevel;
|
||||
uint8_t mFlags;
|
||||
float mScreenFade;
|
||||
|
||||
bool useTransform;
|
||||
DMatrix3x3 transform;
|
||||
|
@ -149,6 +150,7 @@ public:
|
|||
mLightLevel == other.mLightLevel &&
|
||||
mColor1.d == other.mColor1.d &&
|
||||
useTransform == other.useTransform &&
|
||||
mScreenFade == other.mScreenFade &&
|
||||
(
|
||||
!useTransform ||
|
||||
(
|
||||
|
@ -172,7 +174,7 @@ public:
|
|||
int fullscreenautoaspect = 3;
|
||||
int cliptop = -1, clipleft = -1, clipwidth = -1, clipheight = -1;
|
||||
|
||||
int AddCommand(const RenderCommand *data);
|
||||
int AddCommand(RenderCommand *data);
|
||||
void AddIndices(int firstvert, int count, ...);
|
||||
private:
|
||||
void AddIndices(int firstvert, TArray<int> &v);
|
||||
|
@ -187,7 +189,7 @@ public:
|
|||
void AddPoly(FGameTexture *texture, FVector2 *points, int npoints,
|
||||
double originx, double originy, double scalex, double scaley,
|
||||
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, double lightlevel, uint32_t *indices, size_t indexcount);
|
||||
void AddPoly(FGameTexture* img, FVector4 *vt, size_t vtcount, unsigned int *ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, int clipx1, int clipy1, int clipx2, int clipy2);
|
||||
void AddPoly(FGameTexture* img, FVector4 *vt, size_t vtcount, const unsigned int *ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, int clipx1, int clipy1, int clipx2, int clipy2);
|
||||
void FillPolygon(int* rx1, int* ry1, int* xb1, int32_t npoints, int picnum, int palette, int shade, int props, const FVector2& xtex, const FVector2& ytex, const FVector2& otex,
|
||||
int clipx1, int clipy1, int clipx2, int clipy2);
|
||||
void AddFlatFill(int left, int top, int right, int bottom, FGameTexture *src, int local_origin = false, double flatscale = 1.0, PalEntry color = 0xffffffff, ERenderStyle rs = STYLE_Normal);
|
||||
|
|
|
@ -82,8 +82,11 @@ static MusicCallbacks mus_cb = { nullptr, DefaultOpenMusic };
|
|||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
EXTERN_CVAR(Int, snd_mididevice)
|
||||
EXTERN_CVAR(Float, mod_dumb_mastervolume)
|
||||
EXTERN_CVAR(Float, fluid_gain)
|
||||
|
||||
CVAR(Bool, mus_calcgain, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // changing this will only take effect for the next song.
|
||||
|
||||
CVAR(Bool, mus_calcgain, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // changing this will only take effect for the next song.
|
||||
CVAR(Bool, mus_usereplaygain, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // changing this will only take effect for the next song.
|
||||
CUSTOM_CVAR(Float, mus_gainoffset, 0.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // for customizing the base volume
|
||||
{
|
||||
|
@ -107,13 +110,18 @@ void S_SetMusicCallbacks(MusicCallbacks* cb)
|
|||
//==========================================================================
|
||||
|
||||
static std::unique_ptr<SoundStream> musicStream;
|
||||
static TArray<SoundStream*> customStreams;
|
||||
|
||||
SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, StreamCallback cb, void *userdata)
|
||||
{
|
||||
int flags = 0;
|
||||
if (numchannels < 2) flags |= SoundStream::Mono;
|
||||
auto stream = GSnd->CreateStream(cb, int(size), flags, samplerate, userdata);
|
||||
if (stream) stream->Play(true, 1);
|
||||
if (stream)
|
||||
{
|
||||
stream->Play(true, 1);
|
||||
customStreams.Push(stream);
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
@ -122,11 +130,19 @@ void S_StopCustomStream(SoundStream *stream)
|
|||
if (stream)
|
||||
{
|
||||
stream->Stop();
|
||||
auto f = customStreams.Find(stream);
|
||||
if (f < customStreams.Size()) customStreams.Delete(f);
|
||||
delete stream;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void S_PauseAllCustomStreams(bool on)
|
||||
{
|
||||
for (auto s : customStreams)
|
||||
{
|
||||
s->SetPaused(on);
|
||||
}
|
||||
}
|
||||
|
||||
static TArray<int16_t> convert;
|
||||
static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata)
|
||||
|
@ -214,6 +230,9 @@ static bool S_StartMusicPlaying(ZMusic_MusicStream song, bool loop, float rel_vo
|
|||
I_SetRelativeVolume(saved_relative_volume * factor);
|
||||
}
|
||||
ZMusic_Stop(song);
|
||||
// make sure the volume modifiers update properly in case replay gain settings have changed.
|
||||
fluid_gain.Callback();
|
||||
mod_dumb_mastervolume.Callback();
|
||||
if (!ZMusic_Start(song, subsong, loop))
|
||||
{
|
||||
return false;
|
||||
|
@ -488,6 +507,8 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const
|
|||
{
|
||||
mus_playing.replayGain = 0.f;
|
||||
mus_playing.replayGainFactor = dBToAmplitude(mus_gainoffset);
|
||||
fluid_gain.Callback();
|
||||
mod_dumb_mastervolume.Callback();
|
||||
if (!mus_usereplaygain) return;
|
||||
|
||||
FileReader reader = mus_cb.OpenMusic(musicname);
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "version.h"
|
||||
#include <zmusic.h>
|
||||
|
||||
EXTERN_CVAR(Bool, mus_usereplaygain)
|
||||
//==========================================================================
|
||||
//
|
||||
// ADL Midi device
|
||||
|
@ -122,7 +123,16 @@ CUSTOM_CVAR(String, fluid_patchset, GAMENAMELOWERCASE, CVAR_ARCHIVE | CVAR_GLOBA
|
|||
|
||||
CUSTOM_CVAR(Float, fluid_gain, 0.5, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||
{
|
||||
FORWARD_CVAR(fluid_gain);
|
||||
if (!mus_usereplaygain)
|
||||
{
|
||||
FORWARD_CVAR(fluid_gain);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Replay gain will disable the user setting for consistency.
|
||||
float newval;
|
||||
ChangeMusicSetting(zmusic_fluid_gain, mus_playing.handle, 0.5f, & newval);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Bool, fluid_reverb, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||
|
@ -493,6 +503,14 @@ CUSTOM_CVAR(Int, mod_autochip_scan_threshold, 12, CVAR_ARCHIVE | CVAR_GLOBAL
|
|||
|
||||
CUSTOM_CVAR(Float, mod_dumb_mastervolume, 1.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||
{
|
||||
FORWARD_CVAR(mod_dumb_mastervolume);
|
||||
if (!mus_usereplaygain)
|
||||
{
|
||||
FORWARD_CVAR(mod_dumb_mastervolume);
|
||||
}
|
||||
else
|
||||
{
|
||||
float newval;
|
||||
ChangeMusicSetting(zmusic_mod_dumb_mastervolume, mus_playing.handle, 0.5f, &newval);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ class SoundStream;
|
|||
typedef bool(*StreamCallback)(SoundStream* stream, void* buff, int len, void* userdata);
|
||||
SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, StreamCallback cb, void *userdata);
|
||||
void S_StopCustomStream(SoundStream* stream);
|
||||
void S_PauseAllCustomStreams(bool on);
|
||||
|
||||
struct MusicCallbacks
|
||||
{
|
||||
|
|
|
@ -31,6 +31,7 @@ enum EChanFlag
|
|||
CHANF_OVERLAP = 8192, // [MK] Does not stop any sounds in the channel and instead plays over them.
|
||||
CHANF_LOCAL = 16384, // only plays locally for the calling actor
|
||||
CHANF_TRANSIENT = 32768, // Do not record in savegames - used for sounds that get restarted outside the sound system (e.g. ambients in SW and Blood)
|
||||
CHANF_FORCE = 65536, // Start, even if sound is paused.
|
||||
};
|
||||
|
||||
typedef TFlags<EChanFlag> EChanFlags;
|
||||
|
|
|
@ -528,7 +528,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
|
|||
|
||||
// sound is paused and a non-looped sound is being started.
|
||||
// Such a sound would play right after unpausing which wouldn't sound right.
|
||||
if (!(chanflags & CHANF_LOOP) && !(chanflags & (CHANF_UI|CHANF_NOPAUSE)) && SoundPaused)
|
||||
if (!(chanflags & CHANF_LOOP) && !(chanflags & (CHANF_UI|CHANF_NOPAUSE|CHANF_FORCE)) && SoundPaused)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -696,6 +696,12 @@ void ReadBindings(int lump, bool override)
|
|||
dest = &AutomapBindings;
|
||||
sc.MustGetString();
|
||||
}
|
||||
else if (sc.Compare("unbind"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
dest->UnbindKey(sc.String);
|
||||
continue;
|
||||
}
|
||||
key = GetConfigKeyFromName(sc.String);
|
||||
sc.MustGetString();
|
||||
dest->SetBind(key, sc.String, override);
|
||||
|
|
|
@ -76,12 +76,15 @@ void D_ProcessEvents (void)
|
|||
continue;
|
||||
if (ev->type == EV_DeviceChange)
|
||||
UpdateJoystickMenu(I_UpdateDeviceList());
|
||||
if (gamestate == GS_INTRO)
|
||||
continue;
|
||||
if (C_Responder (ev))
|
||||
continue; // console ate the event
|
||||
if (M_Responder (ev))
|
||||
continue; // menu ate the event
|
||||
|
||||
if (gamestate != GS_INTRO) // GS_INTRO blocks the UI.
|
||||
{
|
||||
if (C_Responder(ev))
|
||||
continue; // console ate the event
|
||||
if (M_Responder(ev))
|
||||
continue; // menu ate the event
|
||||
}
|
||||
|
||||
G_Responder (ev);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1287,6 +1287,42 @@ void FScanner::AddSymbol(const char* name, double value)
|
|||
symbols.Insert(name, sym);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FScanner::StartBraces(FScanner::SavedPos* braceend)
|
||||
{
|
||||
if (CheckString("{"))
|
||||
{
|
||||
auto here = SavePos();
|
||||
SkipToEndOfBlock();
|
||||
*braceend = SavePos();
|
||||
RestorePos(here);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptError("'{' expected");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FScanner::FoundEndBrace(FScanner::SavedPos& braceend)
|
||||
{
|
||||
auto here = SavePos();
|
||||
return here.SavedScriptPtr >= braceend.SavedScriptPtr;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// a class that remembers a parser position
|
||||
|
|
|
@ -94,6 +94,8 @@ public:
|
|||
inline void AddSymbol(const char* name, uint32_t value) { return AddSymbol(name, uint64_t(value)); }
|
||||
void AddSymbol(const char* name, double value);
|
||||
void SkipToEndOfBlock();
|
||||
int StartBraces(FScanner::SavedPos* braceend);
|
||||
bool FoundEndBrace(FScanner::SavedPos& braceend);
|
||||
|
||||
static FString TokenName(int token, const char *string=NULL);
|
||||
|
||||
|
@ -113,7 +115,30 @@ public:
|
|||
void MustGetNumber(bool evaluate = false);
|
||||
bool CheckNumber(bool evaluate = false);
|
||||
|
||||
bool GetNumber(int& var, bool evaluate = false)
|
||||
{
|
||||
if (!GetNumber(evaluate)) return false;
|
||||
var = Number;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetString(FString& var)
|
||||
{
|
||||
if (!GetString()) return false;
|
||||
var = String;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetFloat(bool evaluate = false);
|
||||
|
||||
bool GetFloat(double& var, bool evaluate = false)
|
||||
{
|
||||
if (!GetFloat(evaluate)) return false;
|
||||
var = Float;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void MustGetFloat(bool evaluate = false);
|
||||
bool CheckFloat(bool evaluate = false);
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ struct FStartupInfo
|
|||
int LoadLights = -1;
|
||||
int LoadBrightmaps = -1;
|
||||
int LoadWidescreen = -1;
|
||||
int modern = 0;
|
||||
enum
|
||||
{
|
||||
DefaultStartup,
|
||||
|
|
|
@ -293,7 +293,7 @@ bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter)
|
|||
lump_p->Owner = this;
|
||||
lump_p->Flags = LUMPF_FULLPATH|LUMPF_COMPRESSED;
|
||||
lump_p->Position = i;
|
||||
lump_p->CheckEmbedded();
|
||||
lump_p->CheckEmbedded(filter);
|
||||
lump_p++;
|
||||
}
|
||||
// Resize the lump record array to its actual size
|
||||
|
|
|
@ -154,13 +154,28 @@ int FDirectory::AddDirectory(const char *dirpath)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (strstr(fi, ".orig") || strstr(fi, ".bak"))
|
||||
if (strstr(fi, ".orig") || strstr(fi, ".bak") || strstr(fi, ".cache"))
|
||||
{
|
||||
// We shouldn't add backup files to the file system
|
||||
continue;
|
||||
}
|
||||
size_t size = 0;
|
||||
FString fn = FString(dirpath) + fi;
|
||||
|
||||
// The next one is courtesy of EDuke32. :(
|
||||
// Putting cache files in the application directory is very bad style.
|
||||
// Unfortunately, having a garbage file named "texture" present will cause serious problems down the line.
|
||||
if (!stricmp(fi, "textures"))
|
||||
{
|
||||
FILE* f = fopen(fn, "rb");
|
||||
if (f)
|
||||
{
|
||||
char check[3]{};
|
||||
fread(check, 1, 3, f);
|
||||
if (!memcmp(check, "LZ4", 3)) continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (GetFileInfo(fn, &size, nullptr))
|
||||
{
|
||||
AddEntry(fn, (int)size);
|
||||
|
@ -209,7 +224,7 @@ void FDirectory::AddEntry(const char *fullpath, int size)
|
|||
lump_p->LumpSize = size;
|
||||
lump_p->Owner = this;
|
||||
lump_p->Flags = 0;
|
||||
lump_p->CheckEmbedded();
|
||||
lump_p->CheckEmbedded(nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ bool FPakFile::Open(bool quiet, LumpFilterInfo* filter)
|
|||
Lumps[i].Owner = this;
|
||||
Lumps[i].Position = LittleLong(fileinfo[i].filepos);
|
||||
Lumps[i].LumpSize = LittleLong(fileinfo[i].filelen);
|
||||
Lumps[i].CheckEmbedded();
|
||||
Lumps[i].CheckEmbedded(filter);
|
||||
}
|
||||
GenerateHash();
|
||||
PostProcessArchive(&Lumps[0], sizeof(Lumps[0]), filter);
|
||||
|
|
|
@ -233,12 +233,14 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
|||
}
|
||||
|
||||
name.ToLower();
|
||||
if (name.IndexOf("__macosx") == 0)
|
||||
continue; // skip Apple garbage. At this stage only the root folder matters,
|
||||
if (i == 0)
|
||||
{
|
||||
// check for special names, if one of these gets found this must be treated as a normal zip.
|
||||
bool isspecial = name.IndexOf("/") < 0 || (filter && filter->reservedFolders.Find(name) < filter->reservedFolders.Size());
|
||||
if (isspecial) break;
|
||||
name0 = name;
|
||||
name0 = name.Left(name.LastIndexOf("/")+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -252,7 +254,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
|||
// at least one of the more common definition lumps must be present.
|
||||
for (auto &p : filter->requiredPrefixes)
|
||||
{
|
||||
if (name.IndexOf(name0 + p) == 0)
|
||||
if (name.IndexOf(name0 + p) == 0 || name.LastIndexOf(p) == name.Len() - strlen(p))
|
||||
{
|
||||
foundspeciallump = true;
|
||||
break;
|
||||
|
@ -272,7 +274,6 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
|||
|
||||
int len = LittleShort(zip_fh->NameLength);
|
||||
FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len);
|
||||
if (name0.IsNotEmpty()) name = name.Mid(name0.Len());
|
||||
dirptr += sizeof(FZipCentralDirectoryInfo) +
|
||||
LittleShort(zip_fh->NameLength) +
|
||||
LittleShort(zip_fh->ExtraLength) +
|
||||
|
@ -284,7 +285,14 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
|||
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", FileName.GetChars());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (name.IndexOf("__macosx") == 0 || name.IndexOf("__MACOSX") == 0)
|
||||
{
|
||||
skipped++;
|
||||
continue; // Weed out Apple's resource fork garbage right here because it interferes with safe operation.
|
||||
}
|
||||
if (name0.IsNotEmpty()) name = name.Mid(name0.Len());
|
||||
|
||||
// skip Directories
|
||||
if (name.IsEmpty() || (name.Back() == '/' && LittleLong(zip_fh->UncompressedSize) == 0))
|
||||
{
|
||||
|
@ -329,7 +337,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
|||
lump_p->CRC32 = zip_fh->CRC32;
|
||||
lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize);
|
||||
lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset);
|
||||
lump_p->CheckEmbedded();
|
||||
lump_p->CheckEmbedded(filter);
|
||||
|
||||
lump_p++;
|
||||
}
|
||||
|
|
|
@ -76,14 +76,14 @@ struct FileSystem::LumpRecord
|
|||
shortName.String[8] = 0;
|
||||
longName = "";
|
||||
Namespace = lump->GetNamespace();
|
||||
resourceId = 0;
|
||||
resourceId = -1;
|
||||
}
|
||||
else if ((lump->Flags & LUMPF_EMBEDDED) || !lump->getName() || !*lump->getName())
|
||||
{
|
||||
shortName.qword = 0;
|
||||
longName = "";
|
||||
Namespace = ns_hidden;
|
||||
resourceId = 0;
|
||||
resourceId = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -122,7 +122,7 @@ static bool IsWadInFolder(const FResourceFile* const archive, const char* const
|
|||
return 0 == filePath.CompareNoCase(resPath);
|
||||
}
|
||||
|
||||
void FResourceLump::CheckEmbedded()
|
||||
void FResourceLump::CheckEmbedded(LumpFilterInfo* lfi)
|
||||
{
|
||||
// Checks for embedded archives
|
||||
const char *c = strstr(FullName, ".wad");
|
||||
|
@ -130,22 +130,13 @@ void FResourceLump::CheckEmbedded()
|
|||
{
|
||||
Flags |= LUMPF_EMBEDDED;
|
||||
}
|
||||
/* later
|
||||
else
|
||||
else if (lfi) for (auto& fstr : lfi->embeddings)
|
||||
{
|
||||
if (c==NULL) c = strstr(Name, ".zip");
|
||||
if (c==NULL) c = strstr(Name, ".pk3");
|
||||
if (c==NULL) c = strstr(Name, ".7z");
|
||||
if (c==NULL) c = strstr(Name, ".pak");
|
||||
if (c && strlen(c) <= 4)
|
||||
if (!stricmp(FullName, fstr))
|
||||
{
|
||||
// Mark all embedded archives in any directory
|
||||
Flags |= LUMPF_EMBEDDED;
|
||||
memset(Name, 0, 8);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ struct LumpFilterInfo
|
|||
// The following are for checking if the root directory of a zip can be removed.
|
||||
TArray<FString> reservedFolders;
|
||||
TArray<FString> requiredPrefixes;
|
||||
TArray<FString> embeddings;
|
||||
std::function<void()> postprocessFunc;
|
||||
};
|
||||
|
||||
|
@ -111,7 +112,7 @@ public:
|
|||
virtual int GetIndexNum() const { return -1; }
|
||||
virtual int GetNamespace() const { return 0; }
|
||||
void LumpNameSetup(FString iname);
|
||||
void CheckEmbedded();
|
||||
void CheckEmbedded(LumpFilterInfo* lfi);
|
||||
virtual FCompressedBuffer GetRawData();
|
||||
|
||||
void *Lock(); // validates the cache and increases the refcount.
|
||||
|
|
|
@ -232,6 +232,7 @@ DEFINE_ACTION_FUNCTION(FSavegameManager, LoadSavegame)
|
|||
|
||||
void FSavegameManagerBase::DoSave(int Selected, const char *savegamestring)
|
||||
{
|
||||
RemoveNewSaveNode();
|
||||
if (Selected != 0)
|
||||
{
|
||||
auto node = SaveGames[Selected];
|
||||
|
|
|
@ -80,6 +80,8 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height)
|
|||
|
||||
mVertexBuffer = screen->CreateVertexBuffer();
|
||||
mIndexBuffer = screen->CreateIndexBuffer();
|
||||
int data[4] = {};
|
||||
mIndexBuffer->SetData(4, data); // On Vulkan this may not be empty, so set some dummy defaults to avoid crashes.
|
||||
|
||||
unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex);
|
||||
mVertexBuffer->SetData(bytesize, nullptr, false);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
class FRenderState;
|
||||
struct secplane_t;
|
||||
struct subsector_t;
|
||||
|
||||
struct FFlatVertex
|
||||
{
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
#include "tarray.h"
|
||||
#include "vectors.h"
|
||||
|
||||
struct FLevelLocals;
|
||||
|
||||
namespace hwrenderer
|
||||
{
|
||||
|
||||
|
|
|
@ -200,9 +200,8 @@ struct StreamData
|
|||
FVector4 uSplitBottomPlane;
|
||||
|
||||
FVector4 uDetailParms;
|
||||
#ifdef NPOT_EMULATION
|
||||
FVector2 uNpotEmulation;
|
||||
#endif
|
||||
FVector4 uNpotEmulation;
|
||||
FVector4 padding1, padding2, padding3;
|
||||
};
|
||||
|
||||
class FRenderState
|
||||
|
@ -295,7 +294,7 @@ public:
|
|||
mStreamData.uDynLightColor = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
mStreamData.uDetailParms = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
#ifdef NPOT_EMULATION
|
||||
mStreamData.uNpotEmulation = { 0,0 };
|
||||
mStreamData.uNpotEmulation = { 0,0,0,0 };
|
||||
#endif
|
||||
mModelMatrix.loadIdentity();
|
||||
mTextureMatrix.loadIdentity();
|
||||
|
@ -490,7 +489,7 @@ public:
|
|||
void SetNpotEmulation(float factor, float offset)
|
||||
{
|
||||
#ifdef NPOT_EMULATION
|
||||
mStreamData.uNpotEmulation = { offset, factor };
|
||||
mStreamData.uNpotEmulation = { offset, factor, 0, 0 };
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -62,13 +62,7 @@
|
|||
#include "hw_renderstate.h"
|
||||
#include "v_video.h"
|
||||
#include "hwrenderer/data/buffers.h"
|
||||
|
||||
// 57 world units roughly represent one sky texel for the glTranslate call.
|
||||
enum
|
||||
{
|
||||
skyoffsetfactor = 57
|
||||
};
|
||||
|
||||
#include "version.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -150,7 +144,7 @@ FSkyVertexBuffer::~FSkyVertexBuffer()
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FSkyVertexBuffer::SkyVertex(int r, int c, bool zflip)
|
||||
void FSkyVertexBuffer::SkyVertexDoom(int r, int c, bool zflip)
|
||||
{
|
||||
static const FAngle maxSideAngle = 60.f;
|
||||
static const float scale = 10000.;
|
||||
|
@ -187,6 +181,37 @@ void FSkyVertexBuffer::SkyVertex(int r, int c, bool zflip)
|
|||
mVertices.Push(vert);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FSkyVertexBuffer::SkyVertexBuild(int r, int c, bool zflip)
|
||||
{
|
||||
static const FAngle maxSideAngle = 60.f;
|
||||
static const float scale = 10000.;
|
||||
|
||||
FAngle topAngle = (c / (float)mColumns * 360.f);
|
||||
FVector2 pos = topAngle.ToVector(scale);
|
||||
float z = (!zflip) ? (mRows - r) * 4000.f : -(mRows - r) * 4000.f;
|
||||
|
||||
FSkyVertex vert;
|
||||
|
||||
vert.color = r == 0 ? 0xffffff : 0xffffffff;
|
||||
|
||||
// And the texture coordinates.
|
||||
if (zflip) r = mRows * 2 - r;
|
||||
vert.u = 0.5f + (-c / (float)mColumns);
|
||||
vert.v = (r / (float)(2*mRows));
|
||||
|
||||
// And finally the vertex.
|
||||
vert.x = pos.X;
|
||||
vert.y = z - 1.f;
|
||||
vert.z = pos.Y;
|
||||
|
||||
mVertices.Push(vert);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -194,27 +219,58 @@ void FSkyVertexBuffer::SkyVertex(int r, int c, bool zflip)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FSkyVertexBuffer::CreateSkyHemisphere(int hemi)
|
||||
void FSkyVertexBuffer::CreateSkyHemisphereDoom(int hemi)
|
||||
{
|
||||
int r, c;
|
||||
bool zflip = !!(hemi & SKYHEMI_LOWER);
|
||||
|
||||
mPrimStart.Push(mVertices.Size());
|
||||
mPrimStartDoom.Push(mVertices.Size());
|
||||
|
||||
for (c = 0; c < mColumns; c++)
|
||||
{
|
||||
SkyVertex(1, c, zflip);
|
||||
SkyVertexDoom(1, c, zflip);
|
||||
}
|
||||
|
||||
// The total number of triangles per hemisphere can be calculated
|
||||
// as follows: rows * columns * 2 + 2 (for the top cap).
|
||||
for (r = 0; r < mRows; r++)
|
||||
{
|
||||
mPrimStart.Push(mVertices.Size());
|
||||
mPrimStartDoom.Push(mVertices.Size());
|
||||
for (c = 0; c <= mColumns; c++)
|
||||
{
|
||||
SkyVertex(r + zflip, c, zflip);
|
||||
SkyVertex(r + 1 - zflip, c, zflip);
|
||||
SkyVertexDoom(r + zflip, c, zflip);
|
||||
SkyVertexDoom(r + 1 - zflip, c, zflip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FSkyVertexBuffer::CreateSkyHemisphereBuild(int hemi)
|
||||
{
|
||||
int r, c;
|
||||
bool zflip = !!(hemi & SKYHEMI_LOWER);
|
||||
|
||||
mPrimStartBuild.Push(mVertices.Size());
|
||||
|
||||
for (c = 0; c < mColumns; c++)
|
||||
{
|
||||
SkyVertexBuild(1, c, zflip);
|
||||
}
|
||||
|
||||
// The total number of triangles per hemisphere can be calculated
|
||||
// as follows: rows * columns * 2 + 2 (for the top cap).
|
||||
for (r = 0; r < mRows; r++)
|
||||
{
|
||||
mPrimStartBuild.Push(mVertices.Size());
|
||||
for (c = 0; c <= mColumns; c++)
|
||||
{
|
||||
SkyVertexBuild(r + zflip, c, zflip);
|
||||
SkyVertexBuild(r + 1 - zflip, c, zflip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -248,9 +304,13 @@ void FSkyVertexBuffer::CreateDome()
|
|||
|
||||
mColumns = 128;
|
||||
mRows = 4;
|
||||
CreateSkyHemisphere(SKYHEMI_UPPER);
|
||||
CreateSkyHemisphere(SKYHEMI_LOWER);
|
||||
mPrimStart.Push(mVertices.Size());
|
||||
CreateSkyHemisphereDoom(SKYHEMI_UPPER);
|
||||
CreateSkyHemisphereDoom(SKYHEMI_LOWER);
|
||||
mPrimStartDoom.Push(mVertices.Size());
|
||||
|
||||
CreateSkyHemisphereBuild(SKYHEMI_UPPER);
|
||||
CreateSkyHemisphereBuild(SKYHEMI_LOWER);
|
||||
mPrimStartBuild.Push(mVertices.Size());
|
||||
|
||||
mSideStart = mVertices.Size();
|
||||
mFaceStart[0] = mSideStart + 10;
|
||||
|
@ -324,7 +384,7 @@ void FSkyVertexBuffer::CreateDome()
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FSkyVertexBuffer::SetupMatrices(FGameTexture *tex, float x_offset, float y_offset, bool mirror, int mode, VSMatrix &modelMatrix, VSMatrix &textureMatrix, bool tiled)
|
||||
void FSkyVertexBuffer::SetupMatrices(FGameTexture *tex, float x_offset, float y_offset, bool mirror, int mode, VSMatrix &modelMatrix, VSMatrix &textureMatrix, bool tiled, float xscale, float yscale)
|
||||
{
|
||||
float texw = tex->GetDisplayWidth();
|
||||
float texh = tex->GetDisplayHeight();
|
||||
|
@ -332,37 +392,46 @@ void FSkyVertexBuffer::SetupMatrices(FGameTexture *tex, float x_offset, float y_
|
|||
modelMatrix.loadIdentity();
|
||||
modelMatrix.rotate(-180.0f + x_offset, 0.f, 1.f, 0.f);
|
||||
|
||||
float xscale = texw < 1024.f ? floorf(1024.f / float(texw)) : 1.f;
|
||||
float yscale = 1.f;
|
||||
if (xscale == 0) xscale = texw < 1024.f ? floorf(1024.f / float(texw)) : 1.f;
|
||||
auto texskyoffset = tex->GetSkyOffset() + skyoffset;
|
||||
if (texh <= 128 && tiled)
|
||||
if (yscale == 0)
|
||||
{
|
||||
modelMatrix.translate(0.f, (-40 + texskyoffset)*skyoffsetfactor, 0.f);
|
||||
modelMatrix.scale(1.f, 1.2f * 1.17f, 1.f);
|
||||
yscale = 240.f / texh;
|
||||
}
|
||||
else if (texh < 128)
|
||||
{
|
||||
// smaller sky textures must be tiled. We restrict it to 128 sky pixels, though
|
||||
modelMatrix.translate(0.f, -1250.f, 0.f);
|
||||
modelMatrix.scale(1.f, 128 / 230.f, 1.f);
|
||||
yscale = float(128 / texh); // intentionally left as integer.
|
||||
}
|
||||
else if (texh < 200)
|
||||
{
|
||||
modelMatrix.translate(0.f, -1250.f, 0.f);
|
||||
modelMatrix.scale(1.f, texh / 230.f, 1.f);
|
||||
}
|
||||
else if (texh <= 240)
|
||||
{
|
||||
modelMatrix.translate(0.f, (200 - texh + texskyoffset)*skyoffsetfactor, 0.f);
|
||||
modelMatrix.scale(1.f, 1.f + ((texh - 200.f) / 200.f) * 1.17f, 1.f);
|
||||
if (texh <= 128 && tiled)
|
||||
{
|
||||
modelMatrix.translate(0.f, (-40 + texskyoffset) * skyoffsetfactor, 0.f);
|
||||
modelMatrix.scale(1.f, 1.2f * 1.17f, 1.f);
|
||||
yscale = 240.f / texh;
|
||||
}
|
||||
else if (texh < 128)
|
||||
{
|
||||
// smaller sky textures must be tiled. We restrict it to 128 sky pixels, though
|
||||
modelMatrix.translate(0.f, -1250.f, 0.f);
|
||||
modelMatrix.scale(1.f, 128 / 230.f, 1.f);
|
||||
yscale = float(128 / texh); // intentionally left as integer.
|
||||
}
|
||||
else if (texh < 200)
|
||||
{
|
||||
modelMatrix.translate(0.f, -1250.f, 0.f);
|
||||
modelMatrix.scale(1.f, texh / 230.f, 1.f);
|
||||
yscale = 1.f;
|
||||
}
|
||||
else if (texh <= 240)
|
||||
{
|
||||
modelMatrix.translate(0.f, (200 - texh + texskyoffset) * skyoffsetfactor, 0.f);
|
||||
modelMatrix.scale(1.f, 1.f + ((texh - 200.f) / 200.f) * 1.17f, 1.f);
|
||||
yscale = 1.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
modelMatrix.translate(0.f, (-40 + texskyoffset) * skyoffsetfactor, 0.f);
|
||||
modelMatrix.scale(1.f, 1.2f * 1.17f, 1.f);
|
||||
yscale = 240.f / texh;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
modelMatrix.translate(0.f, (-40 + texskyoffset)*skyoffsetfactor, 0.f);
|
||||
modelMatrix.scale(1.f, 1.2f * 1.17f, 1.f);
|
||||
yscale = 240.f / texh;
|
||||
modelMatrix.translate(0.f, (-40 + texskyoffset) * skyoffsetfactor, 0.f);
|
||||
modelMatrix.scale(1.f, 0.8f * 1.17f, 1.f);
|
||||
}
|
||||
textureMatrix.loadIdentity();
|
||||
textureMatrix.scale(mirror ? -xscale : xscale, yscale, 1.f);
|
||||
|
@ -375,7 +444,7 @@ void FSkyVertexBuffer::SetupMatrices(FGameTexture *tex, float x_offset, float y_
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FSkyVertexBuffer::RenderRow(FRenderState& state, EDrawType prim, int row, bool apply)
|
||||
void FSkyVertexBuffer::RenderRow(FRenderState& state, EDrawType prim, int row, TArray<unsigned int>& mPrimStart, bool apply)
|
||||
{
|
||||
state.Draw(prim, mPrimStart[row], mPrimStart[row + 1] - mPrimStart[row]);
|
||||
}
|
||||
|
@ -386,36 +455,35 @@ void FSkyVertexBuffer::RenderRow(FRenderState& state, EDrawType prim, int row, b
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled)
|
||||
void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, int mode, bool which)
|
||||
{
|
||||
if (tex)
|
||||
auto& primStart = which ? mPrimStartBuild : mPrimStartDoom;
|
||||
if (tex && tex->isValid())
|
||||
{
|
||||
state.SetMaterial(tex, UF_Texture, 0, CLAMP_NONE, 0, -1);
|
||||
state.EnableModelMatrix(true);
|
||||
state.EnableTextureMatrix(true);
|
||||
|
||||
SetupMatrices(tex, x_offset, y_offset, mirror, mode, state.mModelMatrix, state.mTextureMatrix, tiled);
|
||||
}
|
||||
|
||||
int rc = mRows + 1;
|
||||
|
||||
// The caps only get drawn for the main layer but not for the overlay.
|
||||
if (mode == FSkyVertexBuffer::SKYMODE_MAINLAYER && tex != NULL)
|
||||
if (mode == FSkyVertexBuffer::SKYMODE_MAINLAYER && tex != nullptr)
|
||||
{
|
||||
auto& col = R_GetSkyCapColor(tex);
|
||||
state.SetObjectColor(col.first);
|
||||
state.EnableTexture(false);
|
||||
RenderRow(state, DT_TriangleFan, 0);
|
||||
RenderRow(state, DT_TriangleFan, 0, primStart);
|
||||
|
||||
state.SetObjectColor(col.second);
|
||||
RenderRow(state, DT_TriangleFan, rc);
|
||||
RenderRow(state, DT_TriangleFan, rc, primStart);
|
||||
state.EnableTexture(true);
|
||||
}
|
||||
state.SetObjectColor(0xffffffff);
|
||||
for (int i = 1; i <= mRows; i++)
|
||||
{
|
||||
RenderRow(state, DT_TriangleStrip, i, i == 1);
|
||||
RenderRow(state, DT_TriangleStrip, rc + i, false);
|
||||
RenderRow(state, DT_TriangleStrip, i, primStart, i == 1);
|
||||
RenderRow(state, DT_TriangleStrip, rc + i, primStart, false);
|
||||
}
|
||||
|
||||
state.EnableTextureMatrix(false);
|
||||
|
@ -423,13 +491,29 @@ void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, float
|
|||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// This is only for Doom-style skies.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled, float xscale, float yscale)
|
||||
{
|
||||
if (tex)
|
||||
{
|
||||
SetupMatrices(tex, x_offset, y_offset, mirror, mode, state.mModelMatrix, state.mTextureMatrix, tiled, xscale, yscale);
|
||||
}
|
||||
RenderDome(state, tex, mode, false);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FSkyVertexBuffer::RenderBox(FRenderState& state, FTextureID texno, FSkyBox* tex, float x_offset, bool sky2, float stretch, const FVector3& skyrotatevector, const FVector3& skyrotatevector2)
|
||||
void FSkyVertexBuffer::RenderBox(FRenderState& state, FSkyBox* tex, float x_offset, bool sky2, float stretch, const FVector3& skyrotatevector, const FVector3& skyrotatevector2)
|
||||
{
|
||||
int faces;
|
||||
|
||||
|
|
|
@ -11,6 +11,12 @@ class IVertexBuffer;
|
|||
struct HWSkyPortal;
|
||||
struct HWDrawInfo;
|
||||
|
||||
// 57 world units roughly represent one sky texel for the glTranslate call.
|
||||
enum
|
||||
{
|
||||
skyoffsetfactor = 57
|
||||
};
|
||||
|
||||
struct FSkyVertex
|
||||
{
|
||||
float x, y, z, u, v;
|
||||
|
@ -55,7 +61,8 @@ public:
|
|||
IVertexBuffer *mVertexBuffer;
|
||||
|
||||
TArray<FSkyVertex> mVertices;
|
||||
TArray<unsigned int> mPrimStart;
|
||||
TArray<unsigned int> mPrimStartDoom;
|
||||
TArray<unsigned int> mPrimStartBuild;
|
||||
|
||||
int mRows, mColumns;
|
||||
|
||||
|
@ -63,15 +70,17 @@ public:
|
|||
int mFaceStart[7];
|
||||
int mSideStart;
|
||||
|
||||
void SkyVertex(int r, int c, bool yflip);
|
||||
void CreateSkyHemisphere(int hemi);
|
||||
void SkyVertexDoom(int r, int c, bool yflip);
|
||||
void SkyVertexBuild(int r, int c, bool yflip);
|
||||
void CreateSkyHemisphereDoom(int hemi);
|
||||
void CreateSkyHemisphereBuild(int hemi);
|
||||
void CreateDome();
|
||||
|
||||
public:
|
||||
|
||||
FSkyVertexBuffer();
|
||||
~FSkyVertexBuffer();
|
||||
void SetupMatrices(FGameTexture *tex, float x_offset, float y_offset, bool mirror, int mode, VSMatrix &modelmatrix, VSMatrix &textureMatrix, bool tiled);
|
||||
void SetupMatrices(FGameTexture *tex, float x_offset, float y_offset, bool mirror, int mode, VSMatrix &modelmatrix, VSMatrix &textureMatrix, bool tiled, float xscale = 0, float vertscale = 0);
|
||||
std::pair<IVertexBuffer *, IIndexBuffer *> GetBufferObjects() const
|
||||
{
|
||||
return std::make_pair(mVertexBuffer, nullptr);
|
||||
|
@ -83,8 +92,9 @@ public:
|
|||
else return mSideStart;
|
||||
}
|
||||
|
||||
void RenderRow(FRenderState& state, EDrawType prim, int row, bool apply = true);
|
||||
void RenderDome(FRenderState& state, FGameTexture* tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled);
|
||||
void RenderBox(FRenderState& state, FTextureID texno, FSkyBox* tex, float x_offset, bool sky2, float stretch, const FVector3& skyrotatevector, const FVector3& skyrotatevector2);
|
||||
void RenderRow(FRenderState& state, EDrawType prim, int row, TArray<unsigned int>& mPrimStart, bool apply = true);
|
||||
void RenderDome(FRenderState& state, FGameTexture* tex, int mode, bool which);
|
||||
void RenderDome(FRenderState& state, FGameTexture* tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled, float xscale = 0, float yscale = 0);
|
||||
void RenderBox(FRenderState& state, FSkyBox* tex, float x_offset, bool sky2, float stretch, const FVector3& skyrotatevector, const FVector3& skyrotatevector2);
|
||||
|
||||
};
|
||||
|
|
|
@ -85,7 +85,6 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state)
|
|||
vb.UploadData(&vertices[0], vertices.Size(), &indices[0], indices.Size());
|
||||
state.SetVertexBuffer(&vb);
|
||||
state.EnableFog(false);
|
||||
state.SetScreenFade(drawer->screenFade);
|
||||
|
||||
for(auto &cmd : commands)
|
||||
{
|
||||
|
@ -94,6 +93,7 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state)
|
|||
state.SetRenderStyle(cmd.mRenderStyle);
|
||||
state.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed));
|
||||
state.EnableFog(2); // Special 2D mode 'fog'.
|
||||
state.SetScreenFade(cmd.mScreenFade);
|
||||
|
||||
state.SetTextureMode(cmd.mDrawMode);
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include "hw_shadowmap.h"
|
||||
|
||||
|
||||
struct sector_t;
|
||||
struct FPortalSceneState;
|
||||
class FSkyVertexBuffer;
|
||||
class IIndexBuffer;
|
||||
|
@ -147,7 +146,7 @@ public:
|
|||
IntRect mScreenViewport;
|
||||
IntRect mSceneViewport;
|
||||
IntRect mOutputLetterbox;
|
||||
float mSceneClearColor[4];
|
||||
float mSceneClearColor[4]{ 0,0,0,255 };
|
||||
|
||||
public:
|
||||
DFrameBuffer (int width=1, int height=1);
|
||||
|
|
|
@ -163,9 +163,8 @@ static const char *shaderBindings = R"(
|
|||
vec4 uSplitBottomPlane;
|
||||
|
||||
vec4 uDetailParms;
|
||||
#ifdef NPOT_EMULATION
|
||||
vec2 uNpotEmulation;
|
||||
#endif
|
||||
vec4 uNpotEmulation;
|
||||
vec4 padding1, padding2, padding3;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 3, std140) uniform StreamUBO {
|
||||
|
@ -297,6 +296,9 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
|
|||
code << defines;
|
||||
code << "\n$placeholder$"; // here the code can later add more needed #defines.
|
||||
code << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n";
|
||||
#ifdef NPOT_EMULATION
|
||||
code << "#define NPOT_EMULATION\n";
|
||||
#endif
|
||||
code << shaderBindings;
|
||||
FString placeholder = "\n";
|
||||
|
||||
|
|
|
@ -390,7 +390,7 @@ void VulkanFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation)
|
|||
|
||||
IHardwareTexture *VulkanFrameBuffer::CreateHardwareTexture(int numchannels)
|
||||
{
|
||||
return new VkHardwareTexture();
|
||||
return new VkHardwareTexture(numchannels);
|
||||
}
|
||||
|
||||
FMaterial* VulkanFrameBuffer::CreateMaterial(FGameTexture* tex, int scaleflags)
|
||||
|
|
|
@ -37,8 +37,9 @@
|
|||
|
||||
VkHardwareTexture *VkHardwareTexture::First = nullptr;
|
||||
|
||||
VkHardwareTexture::VkHardwareTexture()
|
||||
VkHardwareTexture::VkHardwareTexture(int numchannels)
|
||||
{
|
||||
mTexelsize = numchannels;
|
||||
Next = First;
|
||||
First = this;
|
||||
if (Next) Next->Prev = this;
|
||||
|
@ -126,7 +127,8 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
|
|||
if (!tex->isHardwareCanvas())
|
||||
{
|
||||
FTextureBuffer texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData);
|
||||
CreateTexture(texbuffer.mWidth, texbuffer.mHeight, 4, VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer);
|
||||
bool indexed = flags & CTF_Indexed;
|
||||
CreateTexture(texbuffer.mWidth, texbuffer.mHeight,indexed? 1 : 4, indexed? VK_FORMAT_R8_UNORM : VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer, !indexed);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -156,7 +158,7 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
|
|||
}
|
||||
}
|
||||
|
||||
void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels)
|
||||
void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap)
|
||||
{
|
||||
if (w <= 0 || h <= 0)
|
||||
throw CVulkanError("Trying to create zero size texture");
|
||||
|
@ -177,7 +179,7 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form
|
|||
|
||||
ImageBuilder imgbuilder;
|
||||
imgbuilder.setFormat(format);
|
||||
imgbuilder.setSize(w, h, GetMipLevels(w, h));
|
||||
imgbuilder.setSize(w, h, !mipmap ? 1 : GetMipLevels(w, h));
|
||||
imgbuilder.setUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
mImage.Image = imgbuilder.create(fb->device);
|
||||
mImage.Image->SetDebugName("VkHardwareTexture.mImage");
|
||||
|
@ -203,7 +205,7 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form
|
|||
|
||||
fb->FrameDeleteList.Buffers.push_back(std::move(stagingBuffer));
|
||||
|
||||
mImage.GenerateMipmaps(cmdbuffer);
|
||||
if (mipmap) mImage.GenerateMipmaps(cmdbuffer);
|
||||
}
|
||||
|
||||
int VkHardwareTexture::GetMipLevels(int w, int h)
|
||||
|
@ -268,6 +270,7 @@ uint8_t *VkHardwareTexture::MapBuffer()
|
|||
|
||||
unsigned int VkHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, const char *name)
|
||||
{
|
||||
CreateTexture(w, h, mTexelsize, mTexelsize == 4 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R8_UNORM, buffer, mipmap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -371,10 +374,6 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
|
|||
int clampmode = state.mClampMode;
|
||||
int translation = state.mTranslation;
|
||||
|
||||
auto remap = translation <= 0 ? nullptr : GPalette.TranslationToTable(translation);
|
||||
if (remap)
|
||||
translation = remap->Index;
|
||||
|
||||
clampmode = base->GetClampMode(clampmode);
|
||||
|
||||
for (auto& set : mDescriptorSets)
|
||||
|
@ -395,10 +394,23 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
|
|||
MaterialLayerInfo *layer;
|
||||
auto systex = static_cast<VkHardwareTexture*>(GetLayer(0, state.mTranslation, &layer));
|
||||
update.addCombinedImageSampler(descriptor.get(), 0, systex->GetImage(layer->layerTexture, state.mTranslation, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout);
|
||||
for (int i = 1; i < numLayers; i++)
|
||||
|
||||
if (!(layer->scaleFlags & CTF_Indexed))
|
||||
{
|
||||
auto systex = static_cast<VkHardwareTexture*>(GetLayer(i, 0, &layer));
|
||||
update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout);
|
||||
for (int i = 1; i < numLayers; i++)
|
||||
{
|
||||
auto systex = static_cast<VkHardwareTexture*>(GetLayer(i, 0, &layer));
|
||||
update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 1; i < 3; i++)
|
||||
{
|
||||
auto systex = static_cast<VkHardwareTexture*>(GetLayer(i, translation, &layer));
|
||||
update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout);
|
||||
}
|
||||
numLayers = 3;
|
||||
}
|
||||
|
||||
auto dummyImage = fb->GetRenderPassManager()->GetNullTextureView();
|
||||
|
|
|
@ -24,7 +24,7 @@ class VkHardwareTexture : public IHardwareTexture
|
|||
{
|
||||
friend class VkMaterial;
|
||||
public:
|
||||
VkHardwareTexture();
|
||||
VkHardwareTexture(int numchannels);
|
||||
~VkHardwareTexture();
|
||||
|
||||
static void ResetAll();
|
||||
|
@ -45,7 +45,7 @@ public:
|
|||
private:
|
||||
void CreateImage(FTexture *tex, int translation, int flags);
|
||||
|
||||
void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels);
|
||||
void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap);
|
||||
static int GetMipLevels(int w, int h);
|
||||
|
||||
static VkHardwareTexture *First;
|
||||
|
|
|
@ -605,13 +605,13 @@ void DStatusBarCore::DrawGraphic(FGameTexture* tex, double x, double y, int flag
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
void DStatusBarCore::DrawRotated(FTextureID texture, double x, double y, double angle, int flags, double Alpha, double scaleX, double scaleY, PalEntry color, int translation, ERenderStyle style)
|
||||
void DStatusBarCore::DrawRotated(FTextureID texture, double x, double y, int flags, double angle, double Alpha, double scaleX, double scaleY, PalEntry color, int translation, ERenderStyle style)
|
||||
{
|
||||
if (!texture.isValid())
|
||||
return;
|
||||
|
||||
FGameTexture* tex = TexMan.GetGameTexture(texture, !(flags & DI_DONTANIMATE));
|
||||
DrawRotated(tex, x, y, angle, flags, Alpha, scaleX, scaleY, color, translation, style);
|
||||
DrawRotated(tex, x, y, flags, angle, Alpha, scaleX, scaleY, color, translation, style);
|
||||
}
|
||||
|
||||
void DStatusBarCore::DrawRotated(FGameTexture* tex, double x, double y, int flags, double angle, double Alpha, double scaleX, double scaleY, PalEntry color, int translation, ERenderStyle style)
|
||||
|
|
|
@ -186,7 +186,7 @@ public:
|
|||
void StatusbarToRealCoords(double& x, double& y, double& w, double& h) const;
|
||||
void DrawGraphic(FGameTexture* texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent, double clipwidth = -1.0);
|
||||
void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent, double clipwidth = -1.0);
|
||||
void DrawRotated(FTextureID texture, double x, double y, double angle, int flags, double Alpha, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent);
|
||||
void DrawRotated(FTextureID texture, double x, double y, int flags, double angle, double Alpha, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent);
|
||||
void DrawRotated(FGameTexture* tex, double x, double y, int flags, double angle, double Alpha, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent);
|
||||
void DrawString(FFont* font, const FString& cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY, int pt);
|
||||
void TransformRect(double& x, double& y, double& w, double& h, int flags = 0);
|
||||
|
|
|
@ -48,7 +48,6 @@ void AnimTexture::SetFrameSize(int format, int width, int height)
|
|||
FTexture::SetSize(width, height);
|
||||
Image.Resize(width * height * (format == Paletted ? 1 : 3));
|
||||
memset(Image.Data(), 0, Image.Size());
|
||||
CleanHardwareTextures();
|
||||
}
|
||||
|
||||
void AnimTexture::SetFrame(const uint8_t* palette, const void* data_)
|
||||
|
@ -81,7 +80,6 @@ void AnimTexture::SetFrame(const uint8_t* palette, const void* data_)
|
|||
}
|
||||
else memcpy(Image.Data(), data_, Width * Height * (pixelformat == Paletted ? 1 : 3));
|
||||
}
|
||||
CleanHardwareTextures();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -156,10 +154,13 @@ void AnimTextures::SetSize(int format, int width, int height)
|
|||
static_cast<AnimTexture*>(tex[1]->GetTexture())->SetFrameSize(format, width, height);
|
||||
tex[0]->SetSize(width, height);
|
||||
tex[1]->SetSize(width, height);
|
||||
tex[0]->CleanHardwareData();
|
||||
tex[1]->CleanHardwareData();
|
||||
}
|
||||
|
||||
void AnimTextures::SetFrame(const uint8_t* palette, const void* data)
|
||||
{
|
||||
active ^= 1;
|
||||
static_cast<AnimTexture*>(tex[active]->GetTexture())->SetFrame(palette, data);
|
||||
tex[active]->CleanHardwareData();
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "v_video.h"
|
||||
|
||||
static IHardwareTexture* (*layercallback)(int layer, int translation);
|
||||
TArray<UserShaderDesc> usershaders;
|
||||
|
||||
void FMaterial::SetLayerCallback(IHardwareTexture* (*cb)(int layer, int translation))
|
||||
{
|
||||
|
|
81
src/common/thirdparty/earcut.hpp
vendored
81
src/common/thirdparty/earcut.hpp
vendored
|
@ -82,6 +82,7 @@ private:
|
|||
template <typename Polygon> Node* eliminateHoles(const Polygon& points, Node* outerNode);
|
||||
void eliminateHole(Node* hole, Node* outerNode);
|
||||
Node* findHoleBridge(Node* hole, Node* outerNode);
|
||||
bool sectorContainsSector(const Node* m, const Node* p);
|
||||
void indexCurve(Node* start);
|
||||
Node* sortLinked(Node* list);
|
||||
int32_t zOrder(const double x_, const double y_);
|
||||
|
@ -91,6 +92,8 @@ private:
|
|||
double area(const Node* p, const Node* q, const Node* r) const;
|
||||
bool equals(const Node* p1, const Node* p2);
|
||||
bool intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2);
|
||||
bool onSegment(const Node* p, const Node* q, const Node* r);
|
||||
int sign(double val);
|
||||
bool intersectsPolygon(const Node* a, const Node* b);
|
||||
bool locallyInside(const Node* a, const Node* b);
|
||||
bool middleInside(const Node* a, const Node* b);
|
||||
|
@ -116,16 +119,18 @@ private:
|
|||
template <typename... Args>
|
||||
T* construct(Args&&... args) {
|
||||
if (currentIndex >= blockSize) {
|
||||
currentBlock = alloc.allocate(blockSize);
|
||||
currentBlock = alloc_traits::allocate(alloc, blockSize);
|
||||
allocations.emplace_back(currentBlock);
|
||||
currentIndex = 0;
|
||||
}
|
||||
T* object = ¤tBlock[currentIndex++];
|
||||
alloc.construct(object, std::forward<Args>(args)...);
|
||||
alloc_traits::construct(alloc, object, std::forward<Args>(args)...);
|
||||
return object;
|
||||
}
|
||||
void reset(std::size_t newBlockSize) {
|
||||
for (auto allocation : allocations) alloc.deallocate(allocation, blockSize);
|
||||
for (auto allocation : allocations) {
|
||||
alloc_traits::deallocate(alloc, allocation, blockSize);
|
||||
}
|
||||
allocations.clear();
|
||||
blockSize = std::max<std::size_t>(1, newBlockSize);
|
||||
currentBlock = nullptr;
|
||||
|
@ -138,6 +143,7 @@ private:
|
|||
std::size_t blockSize = 1;
|
||||
std::vector<T*> allocations;
|
||||
Alloc alloc;
|
||||
typedef typename std::allocator_traits<Alloc> alloc_traits;
|
||||
};
|
||||
ObjectPool<Node> nodes;
|
||||
};
|
||||
|
@ -165,7 +171,7 @@ void Earcut<N>::operator()(const Polygon& points) {
|
|||
indices.reserve(len + points[0].size());
|
||||
|
||||
Node* outerNode = linkedList(points[0], true);
|
||||
if (!outerNode) return;
|
||||
if (!outerNode || outerNode->prev == outerNode->next) return;
|
||||
|
||||
if (points.size() > 1) outerNode = eliminateHoles(points, outerNode);
|
||||
|
||||
|
@ -244,8 +250,7 @@ Earcut<N>::filterPoints(Node* start, Node* end) {
|
|||
do {
|
||||
again = false;
|
||||
|
||||
if (!p->steiner && (equals(p, p->next) /*|| area(p->prev, p, p->next) == 0*/))
|
||||
{
|
||||
if (!p->steiner && (equals(p, p->next) || area(p->prev, p, p->next) == 0)) {
|
||||
removeNode(p);
|
||||
p = end = p->prev;
|
||||
|
||||
|
@ -304,7 +309,7 @@ void Earcut<N>::earcutLinked(Node* ear, int pass) {
|
|||
|
||||
// if this didn't work, try curing all small self-intersections locally
|
||||
else if (pass == 1) {
|
||||
ear = cureLocalIntersections(ear);
|
||||
ear = cureLocalIntersections(filterPoints(ear));
|
||||
earcutLinked(ear, 2);
|
||||
|
||||
// as a last resort, try splitting the remaining polygon into two
|
||||
|
@ -401,7 +406,7 @@ Earcut<N>::cureLocalIntersections(Node* start) {
|
|||
p = p->next;
|
||||
} while (p != start);
|
||||
|
||||
return p;
|
||||
return filterPoints(p);
|
||||
}
|
||||
|
||||
// try splitting polygon into two and triangulate them independently
|
||||
|
@ -464,6 +469,9 @@ void Earcut<N>::eliminateHole(Node* hole, Node* outerNode) {
|
|||
outerNode = findHoleBridge(hole, outerNode);
|
||||
if (outerNode) {
|
||||
Node* b = splitPolygon(outerNode, hole);
|
||||
|
||||
// filter out colinear points around cuts
|
||||
filterPoints(outerNode, outerNode->next);
|
||||
filterPoints(b, b->next);
|
||||
}
|
||||
}
|
||||
|
@ -497,7 +505,7 @@ Earcut<N>::findHoleBridge(Node* hole, Node* outerNode) {
|
|||
|
||||
if (!m) return 0;
|
||||
|
||||
if (hx == qx) return m->prev;
|
||||
if (hx == qx) return m; // hole touches outer segment; pick leftmost endpoint
|
||||
|
||||
// look for points inside the triangle of hole Vertex, segment intersection and endpoint;
|
||||
// if there are no points found, we have a valid connection;
|
||||
|
@ -507,28 +515,35 @@ Earcut<N>::findHoleBridge(Node* hole, Node* outerNode) {
|
|||
double tanMin = std::numeric_limits<double>::infinity();
|
||||
double tanCur = 0;
|
||||
|
||||
p = m->next;
|
||||
p = m;
|
||||
double mx = m->x;
|
||||
double my = m->y;
|
||||
|
||||
while (p != stop) {
|
||||
do {
|
||||
if (hx >= p->x && p->x >= mx && hx != p->x &&
|
||||
pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p->x, p->y)) {
|
||||
|
||||
tanCur = std::abs(hy - p->y) / (hx - p->x); // tangential
|
||||
|
||||
if ((tanCur < tanMin || (tanCur == tanMin && p->x > m->x)) && locallyInside(p, hole)) {
|
||||
if (locallyInside(p, hole) &&
|
||||
(tanCur < tanMin || (tanCur == tanMin && (p->x > m->x || sectorContainsSector(m, p))))) {
|
||||
m = p;
|
||||
tanMin = tanCur;
|
||||
}
|
||||
}
|
||||
|
||||
p = p->next;
|
||||
}
|
||||
} while (p != stop);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
// whether sector in vertex m contains sector in vertex p in the same coordinates
|
||||
template <typename N>
|
||||
bool Earcut<N>::sectorContainsSector(const Node* m, const Node* p) {
|
||||
return area(m->prev, m, p->prev) < 0 && area(p->next, m, m->next) < 0;
|
||||
}
|
||||
|
||||
// interlink polygon nodes in z-order
|
||||
template <typename N>
|
||||
void Earcut<N>::indexCurve(Node* start) {
|
||||
|
@ -644,7 +659,8 @@ Earcut<N>::getLeftmost(Node* start) {
|
|||
Node* p = start;
|
||||
Node* leftmost = start;
|
||||
do {
|
||||
if (p->x < leftmost->x) leftmost = p;
|
||||
if (p->x < leftmost->x || (p->x == leftmost->x && p->y < leftmost->y))
|
||||
leftmost = p;
|
||||
p = p->next;
|
||||
} while (p != start);
|
||||
|
||||
|
@ -662,8 +678,10 @@ bool Earcut<N>::pointInTriangle(double ax, double ay, double bx, double by, doub
|
|||
// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
|
||||
template <typename N>
|
||||
bool Earcut<N>::isValidDiagonal(Node* a, Node* b) {
|
||||
return a->next->i != b->i && a->prev->i != b->i && !intersectsPolygon(a, b) &&
|
||||
locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b);
|
||||
return a->next->i != b->i && a->prev->i != b->i && !intersectsPolygon(a, b) && // dones't intersect other edges
|
||||
((locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
|
||||
(area(a->prev, a, b->prev) != 0.0 || area(a, b->prev, b) != 0.0)) || // does not create opposite-facing sectors
|
||||
(equals(a, b) && area(a->prev, a, a->next) > 0 && area(b->prev, b, b->next) > 0)); // special zero-length case
|
||||
}
|
||||
|
||||
// signed area of a triangle
|
||||
|
@ -681,10 +699,33 @@ bool Earcut<N>::equals(const Node* p1, const Node* p2) {
|
|||
// check if two segments intersect
|
||||
template <typename N>
|
||||
bool Earcut<N>::intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2) {
|
||||
if ((equals(p1, q1) && equals(p2, q2)) ||
|
||||
(equals(p1, q2) && equals(p2, q1))) return true;
|
||||
return (area(p1, q1, p2) > 0) != (area(p1, q1, q2) > 0) &&
|
||||
(area(p2, q2, p1) > 0) != (area(p2, q2, q1) > 0);
|
||||
int o1 = sign(area(p1, q1, p2));
|
||||
int o2 = sign(area(p1, q1, q2));
|
||||
int o3 = sign(area(p2, q2, p1));
|
||||
int o4 = sign(area(p2, q2, q1));
|
||||
|
||||
if (o1 != o2 && o3 != o4) return true; // general case
|
||||
|
||||
if (o1 == 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
|
||||
if (o2 == 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
|
||||
if (o3 == 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
|
||||
if (o4 == 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// for collinear points p, q, r, check if point q lies on segment pr
|
||||
template <typename N>
|
||||
bool Earcut<N>::onSegment(const Node* p, const Node* q, const Node* r) {
|
||||
return q->x <= std::max<double>(p->x, r->x) &&
|
||||
q->x >= std::min<double>(p->x, r->x) &&
|
||||
q->y <= std::max<double>(p->y, r->y) &&
|
||||
q->y >= std::min<double>(p->y, r->y);
|
||||
}
|
||||
|
||||
template <typename N>
|
||||
int Earcut<N>::sign(double val) {
|
||||
return (0.0 < val) - (val < 0.0);
|
||||
}
|
||||
|
||||
// check if a polygon diagonal intersects any polygon segments
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <algorithm>
|
||||
|
||||
#define MAXWIDTH 12000
|
||||
#define MAXHEIGHT 5000
|
||||
|
@ -101,3 +102,6 @@ enum EStateUseFlags
|
|||
SUF_WEAPON = 4,
|
||||
SUF_ITEM = 8,
|
||||
};
|
||||
|
||||
using std::min;
|
||||
using std::max;
|
||||
|
|
|
@ -103,4 +103,14 @@ inline void fillshort(void* buff, size_t count, uint16_t clear)
|
|||
template<typename T> inline constexpr T Sgn(const T& val) { return (val > 0) - (val < 0); }
|
||||
|
||||
|
||||
inline int sizeToBits(int w)
|
||||
{
|
||||
int j = 15;
|
||||
|
||||
while ((j > 1) && ((1 << j) > w))
|
||||
j--;
|
||||
return j;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,9 +33,7 @@ class VSMatrix {
|
|||
|
||||
public:
|
||||
|
||||
VSMatrix()
|
||||
{
|
||||
}
|
||||
VSMatrix() = default;
|
||||
|
||||
VSMatrix(int)
|
||||
{
|
||||
|
|
|
@ -54,7 +54,6 @@ void AddLightAssociation(const char *actor, const char *frame, const char *light
|
|||
void InitializeActorLights(TArray<FLightAssociation> &LightAssociations);
|
||||
void ParseColorization(FScanner& sc);
|
||||
|
||||
TArray<UserShaderDesc> usershaders;
|
||||
extern TDeletingArray<FLightDefaults *> LightDefaults;
|
||||
extern int AttenuationIsSet;
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
#include "hw_aabbtree.h"
|
||||
|
||||
struct FLevelLocals;
|
||||
|
||||
// Axis aligned bounding box tree used for ray testing treelines.
|
||||
class DoomLevelAABBTree : public hwrenderer::LevelAABBTree
|
||||
{
|
||||
|
|
|
@ -62,7 +62,7 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state)
|
|||
auto skybox = origin->texture[0] ? dynamic_cast<FSkyBox*>(origin->texture[0]->GetTexture()) : nullptr;
|
||||
if (skybox)
|
||||
{
|
||||
vertexBuffer->RenderBox(state, origin->skytexno1, skybox, origin->x_offset[0], origin->sky2, di->Level->info->pixelstretch, di->Level->info->skyrotatevector, di->Level->info->skyrotatevector2);
|
||||
vertexBuffer->RenderBox(state, skybox, origin->x_offset[0], origin->sky2, di->Level->info->pixelstretch, di->Level->info->skyrotatevector, di->Level->info->skyrotatevector2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue