mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-03 09:23:19 +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()))
|
if (mData.Size() > 0 && data->isCompatible(mData.Last()))
|
||||||
{
|
{
|
||||||
// Merge with the last command.
|
// 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;
|
RenderCommand dg;
|
||||||
int method = 0;
|
int method = 0;
|
||||||
|
|
||||||
if (!img->isValid()) return;
|
if (!img || !img->isValid()) return;
|
||||||
|
|
||||||
dg.mType = DrawTypeTriangles;
|
dg.mType = DrawTypeTriangles;
|
||||||
if (clipx1 > 0 || clipy1 > 0 || clipx2 < GetWidth() - 1 || clipy2 < GetHeight() - 1)
|
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);
|
Set(ptr, vt[i].X, vt[i].Y, 0.f, vt[i].Z, vt[i].W, color);
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
dg.mIndexIndex = mIndices.Size();
|
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);
|
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,
|
// 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.
|
// This ensures they are below the HUD, not above it.
|
||||||
|
dg.mScreenFade = screenFade;
|
||||||
mData.Insert(0, dg);
|
mData.Insert(0, dg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,6 +118,7 @@ public:
|
||||||
ETexMode mDrawMode;
|
ETexMode mDrawMode;
|
||||||
uint8_t mLightLevel;
|
uint8_t mLightLevel;
|
||||||
uint8_t mFlags;
|
uint8_t mFlags;
|
||||||
|
float mScreenFade;
|
||||||
|
|
||||||
bool useTransform;
|
bool useTransform;
|
||||||
DMatrix3x3 transform;
|
DMatrix3x3 transform;
|
||||||
|
@ -149,6 +150,7 @@ public:
|
||||||
mLightLevel == other.mLightLevel &&
|
mLightLevel == other.mLightLevel &&
|
||||||
mColor1.d == other.mColor1.d &&
|
mColor1.d == other.mColor1.d &&
|
||||||
useTransform == other.useTransform &&
|
useTransform == other.useTransform &&
|
||||||
|
mScreenFade == other.mScreenFade &&
|
||||||
(
|
(
|
||||||
!useTransform ||
|
!useTransform ||
|
||||||
(
|
(
|
||||||
|
@ -172,7 +174,7 @@ public:
|
||||||
int fullscreenautoaspect = 3;
|
int fullscreenautoaspect = 3;
|
||||||
int cliptop = -1, clipleft = -1, clipwidth = -1, clipheight = -1;
|
int cliptop = -1, clipleft = -1, clipwidth = -1, clipheight = -1;
|
||||||
|
|
||||||
int AddCommand(const RenderCommand *data);
|
int AddCommand(RenderCommand *data);
|
||||||
void AddIndices(int firstvert, int count, ...);
|
void AddIndices(int firstvert, int count, ...);
|
||||||
private:
|
private:
|
||||||
void AddIndices(int firstvert, TArray<int> &v);
|
void AddIndices(int firstvert, TArray<int> &v);
|
||||||
|
@ -187,7 +189,7 @@ public:
|
||||||
void AddPoly(FGameTexture *texture, FVector2 *points, int npoints,
|
void AddPoly(FGameTexture *texture, FVector2 *points, int npoints,
|
||||||
double originx, double originy, double scalex, double scaley,
|
double originx, double originy, double scalex, double scaley,
|
||||||
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, double lightlevel, uint32_t *indices, size_t indexcount);
|
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,
|
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);
|
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);
|
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 -------------------------------------------------
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
EXTERN_CVAR(Int, snd_mididevice)
|
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.
|
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
|
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 std::unique_ptr<SoundStream> musicStream;
|
||||||
|
static TArray<SoundStream*> customStreams;
|
||||||
|
|
||||||
SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, StreamCallback cb, void *userdata)
|
SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, StreamCallback cb, void *userdata)
|
||||||
{
|
{
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if (numchannels < 2) flags |= SoundStream::Mono;
|
if (numchannels < 2) flags |= SoundStream::Mono;
|
||||||
auto stream = GSnd->CreateStream(cb, int(size), flags, samplerate, userdata);
|
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;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,11 +130,19 @@ void S_StopCustomStream(SoundStream *stream)
|
||||||
if (stream)
|
if (stream)
|
||||||
{
|
{
|
||||||
stream->Stop();
|
stream->Stop();
|
||||||
|
auto f = customStreams.Find(stream);
|
||||||
|
if (f < customStreams.Size()) customStreams.Delete(f);
|
||||||
delete stream;
|
delete stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void S_PauseAllCustomStreams(bool on)
|
||||||
|
{
|
||||||
|
for (auto s : customStreams)
|
||||||
|
{
|
||||||
|
s->SetPaused(on);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static TArray<int16_t> convert;
|
static TArray<int16_t> convert;
|
||||||
static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata)
|
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);
|
I_SetRelativeVolume(saved_relative_volume * factor);
|
||||||
}
|
}
|
||||||
ZMusic_Stop(song);
|
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))
|
if (!ZMusic_Start(song, subsong, loop))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -488,6 +507,8 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const
|
||||||
{
|
{
|
||||||
mus_playing.replayGain = 0.f;
|
mus_playing.replayGain = 0.f;
|
||||||
mus_playing.replayGainFactor = dBToAmplitude(mus_gainoffset);
|
mus_playing.replayGainFactor = dBToAmplitude(mus_gainoffset);
|
||||||
|
fluid_gain.Callback();
|
||||||
|
mod_dumb_mastervolume.Callback();
|
||||||
if (!mus_usereplaygain) return;
|
if (!mus_usereplaygain) return;
|
||||||
|
|
||||||
FileReader reader = mus_cb.OpenMusic(musicname);
|
FileReader reader = mus_cb.OpenMusic(musicname);
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include <zmusic.h>
|
#include <zmusic.h>
|
||||||
|
|
||||||
|
EXTERN_CVAR(Bool, mus_usereplaygain)
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// ADL Midi device
|
// 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)
|
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)
|
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)
|
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);
|
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);
|
SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, StreamCallback cb, void *userdata);
|
||||||
void S_StopCustomStream(SoundStream* stream);
|
void S_StopCustomStream(SoundStream* stream);
|
||||||
|
void S_PauseAllCustomStreams(bool on);
|
||||||
|
|
||||||
struct MusicCallbacks
|
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_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_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_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;
|
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.
|
// sound is paused and a non-looped sound is being started.
|
||||||
// Such a sound would play right after unpausing which wouldn't sound right.
|
// 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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -696,6 +696,12 @@ void ReadBindings(int lump, bool override)
|
||||||
dest = &AutomapBindings;
|
dest = &AutomapBindings;
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
}
|
}
|
||||||
|
else if (sc.Compare("unbind"))
|
||||||
|
{
|
||||||
|
sc.MustGetString();
|
||||||
|
dest->UnbindKey(sc.String);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
key = GetConfigKeyFromName(sc.String);
|
key = GetConfigKeyFromName(sc.String);
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
dest->SetBind(key, sc.String, override);
|
dest->SetBind(key, sc.String, override);
|
||||||
|
|
|
@ -76,12 +76,15 @@ void D_ProcessEvents (void)
|
||||||
continue;
|
continue;
|
||||||
if (ev->type == EV_DeviceChange)
|
if (ev->type == EV_DeviceChange)
|
||||||
UpdateJoystickMenu(I_UpdateDeviceList());
|
UpdateJoystickMenu(I_UpdateDeviceList());
|
||||||
if (gamestate == GS_INTRO)
|
|
||||||
continue;
|
if (gamestate != GS_INTRO) // GS_INTRO blocks the UI.
|
||||||
if (C_Responder (ev))
|
{
|
||||||
continue; // console ate the event
|
if (C_Responder(ev))
|
||||||
if (M_Responder (ev))
|
continue; // console ate the event
|
||||||
continue; // menu ate the event
|
if (M_Responder(ev))
|
||||||
|
continue; // menu ate the event
|
||||||
|
}
|
||||||
|
|
||||||
G_Responder (ev);
|
G_Responder (ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1287,6 +1287,42 @@ void FScanner::AddSymbol(const char* name, double value)
|
||||||
symbols.Insert(name, sym);
|
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
|
// 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)); }
|
inline void AddSymbol(const char* name, uint32_t value) { return AddSymbol(name, uint64_t(value)); }
|
||||||
void AddSymbol(const char* name, double value);
|
void AddSymbol(const char* name, double value);
|
||||||
void SkipToEndOfBlock();
|
void SkipToEndOfBlock();
|
||||||
|
int StartBraces(FScanner::SavedPos* braceend);
|
||||||
|
bool FoundEndBrace(FScanner::SavedPos& braceend);
|
||||||
|
|
||||||
static FString TokenName(int token, const char *string=NULL);
|
static FString TokenName(int token, const char *string=NULL);
|
||||||
|
|
||||||
|
@ -113,7 +115,30 @@ public:
|
||||||
void MustGetNumber(bool evaluate = false);
|
void MustGetNumber(bool evaluate = false);
|
||||||
bool CheckNumber(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(bool evaluate = false);
|
||||||
|
|
||||||
|
bool GetFloat(double& var, bool evaluate = false)
|
||||||
|
{
|
||||||
|
if (!GetFloat(evaluate)) return false;
|
||||||
|
var = Float;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MustGetFloat(bool evaluate = false);
|
void MustGetFloat(bool evaluate = false);
|
||||||
bool CheckFloat(bool evaluate = false);
|
bool CheckFloat(bool evaluate = false);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ struct FStartupInfo
|
||||||
int LoadLights = -1;
|
int LoadLights = -1;
|
||||||
int LoadBrightmaps = -1;
|
int LoadBrightmaps = -1;
|
||||||
int LoadWidescreen = -1;
|
int LoadWidescreen = -1;
|
||||||
int modern = 0;
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
DefaultStartup,
|
DefaultStartup,
|
||||||
|
|
|
@ -293,7 +293,7 @@ bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter)
|
||||||
lump_p->Owner = this;
|
lump_p->Owner = this;
|
||||||
lump_p->Flags = LUMPF_FULLPATH|LUMPF_COMPRESSED;
|
lump_p->Flags = LUMPF_FULLPATH|LUMPF_COMPRESSED;
|
||||||
lump_p->Position = i;
|
lump_p->Position = i;
|
||||||
lump_p->CheckEmbedded();
|
lump_p->CheckEmbedded(filter);
|
||||||
lump_p++;
|
lump_p++;
|
||||||
}
|
}
|
||||||
// Resize the lump record array to its actual size
|
// Resize the lump record array to its actual size
|
||||||
|
|
|
@ -154,13 +154,28 @@ int FDirectory::AddDirectory(const char *dirpath)
|
||||||
}
|
}
|
||||||
else
|
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
|
// We shouldn't add backup files to the file system
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
FString fn = FString(dirpath) + fi;
|
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))
|
if (GetFileInfo(fn, &size, nullptr))
|
||||||
{
|
{
|
||||||
AddEntry(fn, (int)size);
|
AddEntry(fn, (int)size);
|
||||||
|
@ -209,7 +224,7 @@ void FDirectory::AddEntry(const char *fullpath, int size)
|
||||||
lump_p->LumpSize = size;
|
lump_p->LumpSize = size;
|
||||||
lump_p->Owner = this;
|
lump_p->Owner = this;
|
||||||
lump_p->Flags = 0;
|
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].Owner = this;
|
||||||
Lumps[i].Position = LittleLong(fileinfo[i].filepos);
|
Lumps[i].Position = LittleLong(fileinfo[i].filepos);
|
||||||
Lumps[i].LumpSize = LittleLong(fileinfo[i].filelen);
|
Lumps[i].LumpSize = LittleLong(fileinfo[i].filelen);
|
||||||
Lumps[i].CheckEmbedded();
|
Lumps[i].CheckEmbedded(filter);
|
||||||
}
|
}
|
||||||
GenerateHash();
|
GenerateHash();
|
||||||
PostProcessArchive(&Lumps[0], sizeof(Lumps[0]), filter);
|
PostProcessArchive(&Lumps[0], sizeof(Lumps[0]), filter);
|
||||||
|
|
|
@ -233,12 +233,14 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
name.ToLower();
|
name.ToLower();
|
||||||
|
if (name.IndexOf("__macosx") == 0)
|
||||||
|
continue; // skip Apple garbage. At this stage only the root folder matters,
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
// check for special names, if one of these gets found this must be treated as a normal zip.
|
// 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());
|
bool isspecial = name.IndexOf("/") < 0 || (filter && filter->reservedFolders.Find(name) < filter->reservedFolders.Size());
|
||||||
if (isspecial) break;
|
if (isspecial) break;
|
||||||
name0 = name;
|
name0 = name.Left(name.LastIndexOf("/")+1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -252,7 +254,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
||||||
// at least one of the more common definition lumps must be present.
|
// at least one of the more common definition lumps must be present.
|
||||||
for (auto &p : filter->requiredPrefixes)
|
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;
|
foundspeciallump = true;
|
||||||
break;
|
break;
|
||||||
|
@ -272,7 +274,6 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
||||||
|
|
||||||
int len = LittleShort(zip_fh->NameLength);
|
int len = LittleShort(zip_fh->NameLength);
|
||||||
FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len);
|
FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len);
|
||||||
if (name0.IsNotEmpty()) name = name.Mid(name0.Len());
|
|
||||||
dirptr += sizeof(FZipCentralDirectoryInfo) +
|
dirptr += sizeof(FZipCentralDirectoryInfo) +
|
||||||
LittleShort(zip_fh->NameLength) +
|
LittleShort(zip_fh->NameLength) +
|
||||||
LittleShort(zip_fh->ExtraLength) +
|
LittleShort(zip_fh->ExtraLength) +
|
||||||
|
@ -285,6 +286,13 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
||||||
return false;
|
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
|
// skip Directories
|
||||||
if (name.IsEmpty() || (name.Back() == '/' && LittleLong(zip_fh->UncompressedSize) == 0))
|
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->CRC32 = zip_fh->CRC32;
|
||||||
lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize);
|
lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize);
|
||||||
lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset);
|
lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset);
|
||||||
lump_p->CheckEmbedded();
|
lump_p->CheckEmbedded(filter);
|
||||||
|
|
||||||
lump_p++;
|
lump_p++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,14 +76,14 @@ struct FileSystem::LumpRecord
|
||||||
shortName.String[8] = 0;
|
shortName.String[8] = 0;
|
||||||
longName = "";
|
longName = "";
|
||||||
Namespace = lump->GetNamespace();
|
Namespace = lump->GetNamespace();
|
||||||
resourceId = 0;
|
resourceId = -1;
|
||||||
}
|
}
|
||||||
else if ((lump->Flags & LUMPF_EMBEDDED) || !lump->getName() || !*lump->getName())
|
else if ((lump->Flags & LUMPF_EMBEDDED) || !lump->getName() || !*lump->getName())
|
||||||
{
|
{
|
||||||
shortName.qword = 0;
|
shortName.qword = 0;
|
||||||
longName = "";
|
longName = "";
|
||||||
Namespace = ns_hidden;
|
Namespace = ns_hidden;
|
||||||
resourceId = 0;
|
resourceId = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -122,7 +122,7 @@ static bool IsWadInFolder(const FResourceFile* const archive, const char* const
|
||||||
return 0 == filePath.CompareNoCase(resPath);
|
return 0 == filePath.CompareNoCase(resPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FResourceLump::CheckEmbedded()
|
void FResourceLump::CheckEmbedded(LumpFilterInfo* lfi)
|
||||||
{
|
{
|
||||||
// Checks for embedded archives
|
// Checks for embedded archives
|
||||||
const char *c = strstr(FullName, ".wad");
|
const char *c = strstr(FullName, ".wad");
|
||||||
|
@ -130,22 +130,13 @@ void FResourceLump::CheckEmbedded()
|
||||||
{
|
{
|
||||||
Flags |= LUMPF_EMBEDDED;
|
Flags |= LUMPF_EMBEDDED;
|
||||||
}
|
}
|
||||||
/* later
|
else if (lfi) for (auto& fstr : lfi->embeddings)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (c==NULL) c = strstr(Name, ".zip");
|
if (!stricmp(FullName, fstr))
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
// Mark all embedded archives in any directory
|
|
||||||
Flags |= LUMPF_EMBEDDED;
|
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.
|
// The following are for checking if the root directory of a zip can be removed.
|
||||||
TArray<FString> reservedFolders;
|
TArray<FString> reservedFolders;
|
||||||
TArray<FString> requiredPrefixes;
|
TArray<FString> requiredPrefixes;
|
||||||
|
TArray<FString> embeddings;
|
||||||
std::function<void()> postprocessFunc;
|
std::function<void()> postprocessFunc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -111,7 +112,7 @@ public:
|
||||||
virtual int GetIndexNum() const { return -1; }
|
virtual int GetIndexNum() const { return -1; }
|
||||||
virtual int GetNamespace() const { return 0; }
|
virtual int GetNamespace() const { return 0; }
|
||||||
void LumpNameSetup(FString iname);
|
void LumpNameSetup(FString iname);
|
||||||
void CheckEmbedded();
|
void CheckEmbedded(LumpFilterInfo* lfi);
|
||||||
virtual FCompressedBuffer GetRawData();
|
virtual FCompressedBuffer GetRawData();
|
||||||
|
|
||||||
void *Lock(); // validates the cache and increases the refcount.
|
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)
|
void FSavegameManagerBase::DoSave(int Selected, const char *savegamestring)
|
||||||
{
|
{
|
||||||
|
RemoveNewSaveNode();
|
||||||
if (Selected != 0)
|
if (Selected != 0)
|
||||||
{
|
{
|
||||||
auto node = SaveGames[Selected];
|
auto node = SaveGames[Selected];
|
||||||
|
|
|
@ -80,6 +80,8 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height)
|
||||||
|
|
||||||
mVertexBuffer = screen->CreateVertexBuffer();
|
mVertexBuffer = screen->CreateVertexBuffer();
|
||||||
mIndexBuffer = screen->CreateIndexBuffer();
|
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);
|
unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex);
|
||||||
mVertexBuffer->SetData(bytesize, nullptr, false);
|
mVertexBuffer->SetData(bytesize, nullptr, false);
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
class FRenderState;
|
class FRenderState;
|
||||||
struct secplane_t;
|
struct secplane_t;
|
||||||
struct subsector_t;
|
|
||||||
|
|
||||||
struct FFlatVertex
|
struct FFlatVertex
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
#include "tarray.h"
|
#include "tarray.h"
|
||||||
#include "vectors.h"
|
#include "vectors.h"
|
||||||
|
|
||||||
struct FLevelLocals;
|
|
||||||
|
|
||||||
namespace hwrenderer
|
namespace hwrenderer
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -200,9 +200,8 @@ struct StreamData
|
||||||
FVector4 uSplitBottomPlane;
|
FVector4 uSplitBottomPlane;
|
||||||
|
|
||||||
FVector4 uDetailParms;
|
FVector4 uDetailParms;
|
||||||
#ifdef NPOT_EMULATION
|
FVector4 uNpotEmulation;
|
||||||
FVector2 uNpotEmulation;
|
FVector4 padding1, padding2, padding3;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FRenderState
|
class FRenderState
|
||||||
|
@ -295,7 +294,7 @@ public:
|
||||||
mStreamData.uDynLightColor = { 0.0f, 0.0f, 0.0f, 1.0f };
|
mStreamData.uDynLightColor = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||||
mStreamData.uDetailParms = { 0.0f, 0.0f, 0.0f, 0.0f };
|
mStreamData.uDetailParms = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
#ifdef NPOT_EMULATION
|
#ifdef NPOT_EMULATION
|
||||||
mStreamData.uNpotEmulation = { 0,0 };
|
mStreamData.uNpotEmulation = { 0,0,0,0 };
|
||||||
#endif
|
#endif
|
||||||
mModelMatrix.loadIdentity();
|
mModelMatrix.loadIdentity();
|
||||||
mTextureMatrix.loadIdentity();
|
mTextureMatrix.loadIdentity();
|
||||||
|
@ -490,7 +489,7 @@ public:
|
||||||
void SetNpotEmulation(float factor, float offset)
|
void SetNpotEmulation(float factor, float offset)
|
||||||
{
|
{
|
||||||
#ifdef NPOT_EMULATION
|
#ifdef NPOT_EMULATION
|
||||||
mStreamData.uNpotEmulation = { offset, factor };
|
mStreamData.uNpotEmulation = { offset, factor, 0, 0 };
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,13 +62,7 @@
|
||||||
#include "hw_renderstate.h"
|
#include "hw_renderstate.h"
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
#include "hwrenderer/data/buffers.h"
|
#include "hwrenderer/data/buffers.h"
|
||||||
|
#include "version.h"
|
||||||
// 57 world units roughly represent one sky texel for the glTranslate call.
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
skyoffsetfactor = 57
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -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 FAngle maxSideAngle = 60.f;
|
||||||
static const float scale = 10000.;
|
static const float scale = 10000.;
|
||||||
|
@ -187,6 +181,37 @@ void FSkyVertexBuffer::SkyVertex(int r, int c, bool zflip)
|
||||||
mVertices.Push(vert);
|
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;
|
int r, c;
|
||||||
bool zflip = !!(hemi & SKYHEMI_LOWER);
|
bool zflip = !!(hemi & SKYHEMI_LOWER);
|
||||||
|
|
||||||
mPrimStart.Push(mVertices.Size());
|
mPrimStartDoom.Push(mVertices.Size());
|
||||||
|
|
||||||
for (c = 0; c < mColumns; c++)
|
for (c = 0; c < mColumns; c++)
|
||||||
{
|
{
|
||||||
SkyVertex(1, c, zflip);
|
SkyVertexDoom(1, c, zflip);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The total number of triangles per hemisphere can be calculated
|
// The total number of triangles per hemisphere can be calculated
|
||||||
// as follows: rows * columns * 2 + 2 (for the top cap).
|
// as follows: rows * columns * 2 + 2 (for the top cap).
|
||||||
for (r = 0; r < mRows; r++)
|
for (r = 0; r < mRows; r++)
|
||||||
{
|
{
|
||||||
mPrimStart.Push(mVertices.Size());
|
mPrimStartDoom.Push(mVertices.Size());
|
||||||
for (c = 0; c <= mColumns; c++)
|
for (c = 0; c <= mColumns; c++)
|
||||||
{
|
{
|
||||||
SkyVertex(r + zflip, c, zflip);
|
SkyVertexDoom(r + zflip, c, zflip);
|
||||||
SkyVertex(r + 1 - 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;
|
mColumns = 128;
|
||||||
mRows = 4;
|
mRows = 4;
|
||||||
CreateSkyHemisphere(SKYHEMI_UPPER);
|
CreateSkyHemisphereDoom(SKYHEMI_UPPER);
|
||||||
CreateSkyHemisphere(SKYHEMI_LOWER);
|
CreateSkyHemisphereDoom(SKYHEMI_LOWER);
|
||||||
mPrimStart.Push(mVertices.Size());
|
mPrimStartDoom.Push(mVertices.Size());
|
||||||
|
|
||||||
|
CreateSkyHemisphereBuild(SKYHEMI_UPPER);
|
||||||
|
CreateSkyHemisphereBuild(SKYHEMI_LOWER);
|
||||||
|
mPrimStartBuild.Push(mVertices.Size());
|
||||||
|
|
||||||
mSideStart = mVertices.Size();
|
mSideStart = mVertices.Size();
|
||||||
mFaceStart[0] = mSideStart + 10;
|
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 texw = tex->GetDisplayWidth();
|
||||||
float texh = tex->GetDisplayHeight();
|
float texh = tex->GetDisplayHeight();
|
||||||
|
@ -332,37 +392,46 @@ void FSkyVertexBuffer::SetupMatrices(FGameTexture *tex, float x_offset, float y_
|
||||||
modelMatrix.loadIdentity();
|
modelMatrix.loadIdentity();
|
||||||
modelMatrix.rotate(-180.0f + x_offset, 0.f, 1.f, 0.f);
|
modelMatrix.rotate(-180.0f + x_offset, 0.f, 1.f, 0.f);
|
||||||
|
|
||||||
float xscale = texw < 1024.f ? floorf(1024.f / float(texw)) : 1.f;
|
if (xscale == 0) xscale = texw < 1024.f ? floorf(1024.f / float(texw)) : 1.f;
|
||||||
float yscale = 1.f;
|
|
||||||
auto texskyoffset = tex->GetSkyOffset() + skyoffset;
|
auto texskyoffset = tex->GetSkyOffset() + skyoffset;
|
||||||
if (texh <= 128 && tiled)
|
if (yscale == 0)
|
||||||
{
|
{
|
||||||
modelMatrix.translate(0.f, (-40 + texskyoffset)*skyoffsetfactor, 0.f);
|
if (texh <= 128 && tiled)
|
||||||
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, 1.2f * 1.17f, 1.f);
|
||||||
else if (texh < 128)
|
yscale = 240.f / texh;
|
||||||
{
|
}
|
||||||
// smaller sky textures must be tiled. We restrict it to 128 sky pixels, though
|
else if (texh < 128)
|
||||||
modelMatrix.translate(0.f, -1250.f, 0.f);
|
{
|
||||||
modelMatrix.scale(1.f, 128 / 230.f, 1.f);
|
// smaller sky textures must be tiled. We restrict it to 128 sky pixels, though
|
||||||
yscale = float(128 / texh); // intentionally left as integer.
|
modelMatrix.translate(0.f, -1250.f, 0.f);
|
||||||
}
|
modelMatrix.scale(1.f, 128 / 230.f, 1.f);
|
||||||
else if (texh < 200)
|
yscale = float(128 / texh); // intentionally left as integer.
|
||||||
{
|
}
|
||||||
modelMatrix.translate(0.f, -1250.f, 0.f);
|
else if (texh < 200)
|
||||||
modelMatrix.scale(1.f, texh / 230.f, 1.f);
|
{
|
||||||
}
|
modelMatrix.translate(0.f, -1250.f, 0.f);
|
||||||
else if (texh <= 240)
|
modelMatrix.scale(1.f, texh / 230.f, 1.f);
|
||||||
{
|
yscale = 1.f;
|
||||||
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);
|
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
|
else
|
||||||
{
|
{
|
||||||
modelMatrix.translate(0.f, (-40 + texskyoffset)*skyoffsetfactor, 0.f);
|
modelMatrix.translate(0.f, (-40 + texskyoffset) * skyoffsetfactor, 0.f);
|
||||||
modelMatrix.scale(1.f, 1.2f * 1.17f, 1.f);
|
modelMatrix.scale(1.f, 0.8f * 1.17f, 1.f);
|
||||||
yscale = 240.f / texh;
|
|
||||||
}
|
}
|
||||||
textureMatrix.loadIdentity();
|
textureMatrix.loadIdentity();
|
||||||
textureMatrix.scale(mirror ? -xscale : xscale, yscale, 1.f);
|
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]);
|
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.SetMaterial(tex, UF_Texture, 0, CLAMP_NONE, 0, -1);
|
||||||
state.EnableModelMatrix(true);
|
state.EnableModelMatrix(true);
|
||||||
state.EnableTextureMatrix(true);
|
state.EnableTextureMatrix(true);
|
||||||
|
|
||||||
SetupMatrices(tex, x_offset, y_offset, mirror, mode, state.mModelMatrix, state.mTextureMatrix, tiled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc = mRows + 1;
|
int rc = mRows + 1;
|
||||||
|
|
||||||
// The caps only get drawn for the main layer but not for the overlay.
|
// 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);
|
auto& col = R_GetSkyCapColor(tex);
|
||||||
state.SetObjectColor(col.first);
|
state.SetObjectColor(col.first);
|
||||||
state.EnableTexture(false);
|
state.EnableTexture(false);
|
||||||
RenderRow(state, DT_TriangleFan, 0);
|
RenderRow(state, DT_TriangleFan, 0, primStart);
|
||||||
|
|
||||||
state.SetObjectColor(col.second);
|
state.SetObjectColor(col.second);
|
||||||
RenderRow(state, DT_TriangleFan, rc);
|
RenderRow(state, DT_TriangleFan, rc, primStart);
|
||||||
state.EnableTexture(true);
|
state.EnableTexture(true);
|
||||||
}
|
}
|
||||||
state.SetObjectColor(0xffffffff);
|
state.SetObjectColor(0xffffffff);
|
||||||
for (int i = 1; i <= mRows; i++)
|
for (int i = 1; i <= mRows; i++)
|
||||||
{
|
{
|
||||||
RenderRow(state, DT_TriangleStrip, i, i == 1);
|
RenderRow(state, DT_TriangleStrip, i, primStart, i == 1);
|
||||||
RenderRow(state, DT_TriangleStrip, rc + i, false);
|
RenderRow(state, DT_TriangleStrip, rc + i, primStart, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.EnableTextureMatrix(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;
|
int faces;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,12 @@ class IVertexBuffer;
|
||||||
struct HWSkyPortal;
|
struct HWSkyPortal;
|
||||||
struct HWDrawInfo;
|
struct HWDrawInfo;
|
||||||
|
|
||||||
|
// 57 world units roughly represent one sky texel for the glTranslate call.
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
skyoffsetfactor = 57
|
||||||
|
};
|
||||||
|
|
||||||
struct FSkyVertex
|
struct FSkyVertex
|
||||||
{
|
{
|
||||||
float x, y, z, u, v;
|
float x, y, z, u, v;
|
||||||
|
@ -55,7 +61,8 @@ public:
|
||||||
IVertexBuffer *mVertexBuffer;
|
IVertexBuffer *mVertexBuffer;
|
||||||
|
|
||||||
TArray<FSkyVertex> mVertices;
|
TArray<FSkyVertex> mVertices;
|
||||||
TArray<unsigned int> mPrimStart;
|
TArray<unsigned int> mPrimStartDoom;
|
||||||
|
TArray<unsigned int> mPrimStartBuild;
|
||||||
|
|
||||||
int mRows, mColumns;
|
int mRows, mColumns;
|
||||||
|
|
||||||
|
@ -63,15 +70,17 @@ public:
|
||||||
int mFaceStart[7];
|
int mFaceStart[7];
|
||||||
int mSideStart;
|
int mSideStart;
|
||||||
|
|
||||||
void SkyVertex(int r, int c, bool yflip);
|
void SkyVertexDoom(int r, int c, bool yflip);
|
||||||
void CreateSkyHemisphere(int hemi);
|
void SkyVertexBuild(int r, int c, bool yflip);
|
||||||
|
void CreateSkyHemisphereDoom(int hemi);
|
||||||
|
void CreateSkyHemisphereBuild(int hemi);
|
||||||
void CreateDome();
|
void CreateDome();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FSkyVertexBuffer();
|
FSkyVertexBuffer();
|
||||||
~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
|
std::pair<IVertexBuffer *, IIndexBuffer *> GetBufferObjects() const
|
||||||
{
|
{
|
||||||
return std::make_pair(mVertexBuffer, nullptr);
|
return std::make_pair(mVertexBuffer, nullptr);
|
||||||
|
@ -83,8 +92,9 @@ public:
|
||||||
else return mSideStart;
|
else return mSideStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderRow(FRenderState& state, EDrawType prim, int row, bool apply = true);
|
void RenderRow(FRenderState& state, EDrawType prim, int row, TArray<unsigned int>& mPrimStart, bool apply = true);
|
||||||
void RenderDome(FRenderState& state, FGameTexture* tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled);
|
void RenderDome(FRenderState& state, FGameTexture* tex, int mode, bool which);
|
||||||
void RenderBox(FRenderState& state, FTextureID texno, FSkyBox* tex, float x_offset, bool sky2, float stretch, const FVector3& skyrotatevector, const FVector3& skyrotatevector2);
|
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());
|
vb.UploadData(&vertices[0], vertices.Size(), &indices[0], indices.Size());
|
||||||
state.SetVertexBuffer(&vb);
|
state.SetVertexBuffer(&vb);
|
||||||
state.EnableFog(false);
|
state.EnableFog(false);
|
||||||
state.SetScreenFade(drawer->screenFade);
|
|
||||||
|
|
||||||
for(auto &cmd : commands)
|
for(auto &cmd : commands)
|
||||||
{
|
{
|
||||||
|
@ -94,6 +93,7 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state)
|
||||||
state.SetRenderStyle(cmd.mRenderStyle);
|
state.SetRenderStyle(cmd.mRenderStyle);
|
||||||
state.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed));
|
state.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed));
|
||||||
state.EnableFog(2); // Special 2D mode 'fog'.
|
state.EnableFog(2); // Special 2D mode 'fog'.
|
||||||
|
state.SetScreenFade(cmd.mScreenFade);
|
||||||
|
|
||||||
state.SetTextureMode(cmd.mDrawMode);
|
state.SetTextureMode(cmd.mDrawMode);
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,6 @@
|
||||||
#include "hw_shadowmap.h"
|
#include "hw_shadowmap.h"
|
||||||
|
|
||||||
|
|
||||||
struct sector_t;
|
|
||||||
struct FPortalSceneState;
|
struct FPortalSceneState;
|
||||||
class FSkyVertexBuffer;
|
class FSkyVertexBuffer;
|
||||||
class IIndexBuffer;
|
class IIndexBuffer;
|
||||||
|
@ -147,7 +146,7 @@ public:
|
||||||
IntRect mScreenViewport;
|
IntRect mScreenViewport;
|
||||||
IntRect mSceneViewport;
|
IntRect mSceneViewport;
|
||||||
IntRect mOutputLetterbox;
|
IntRect mOutputLetterbox;
|
||||||
float mSceneClearColor[4];
|
float mSceneClearColor[4]{ 0,0,0,255 };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DFrameBuffer (int width=1, int height=1);
|
DFrameBuffer (int width=1, int height=1);
|
||||||
|
|
|
@ -163,9 +163,8 @@ static const char *shaderBindings = R"(
|
||||||
vec4 uSplitBottomPlane;
|
vec4 uSplitBottomPlane;
|
||||||
|
|
||||||
vec4 uDetailParms;
|
vec4 uDetailParms;
|
||||||
#ifdef NPOT_EMULATION
|
vec4 uNpotEmulation;
|
||||||
vec2 uNpotEmulation;
|
vec4 padding1, padding2, padding3;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(set = 0, binding = 3, std140) uniform StreamUBO {
|
layout(set = 0, binding = 3, std140) uniform StreamUBO {
|
||||||
|
@ -297,6 +296,9 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
|
||||||
code << defines;
|
code << defines;
|
||||||
code << "\n$placeholder$"; // here the code can later add more needed #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";
|
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;
|
code << shaderBindings;
|
||||||
FString placeholder = "\n";
|
FString placeholder = "\n";
|
||||||
|
|
||||||
|
|
|
@ -390,7 +390,7 @@ void VulkanFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation)
|
||||||
|
|
||||||
IHardwareTexture *VulkanFrameBuffer::CreateHardwareTexture(int numchannels)
|
IHardwareTexture *VulkanFrameBuffer::CreateHardwareTexture(int numchannels)
|
||||||
{
|
{
|
||||||
return new VkHardwareTexture();
|
return new VkHardwareTexture(numchannels);
|
||||||
}
|
}
|
||||||
|
|
||||||
FMaterial* VulkanFrameBuffer::CreateMaterial(FGameTexture* tex, int scaleflags)
|
FMaterial* VulkanFrameBuffer::CreateMaterial(FGameTexture* tex, int scaleflags)
|
||||||
|
|
|
@ -37,8 +37,9 @@
|
||||||
|
|
||||||
VkHardwareTexture *VkHardwareTexture::First = nullptr;
|
VkHardwareTexture *VkHardwareTexture::First = nullptr;
|
||||||
|
|
||||||
VkHardwareTexture::VkHardwareTexture()
|
VkHardwareTexture::VkHardwareTexture(int numchannels)
|
||||||
{
|
{
|
||||||
|
mTexelsize = numchannels;
|
||||||
Next = First;
|
Next = First;
|
||||||
First = this;
|
First = this;
|
||||||
if (Next) Next->Prev = this;
|
if (Next) Next->Prev = this;
|
||||||
|
@ -126,7 +127,8 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
|
||||||
if (!tex->isHardwareCanvas())
|
if (!tex->isHardwareCanvas())
|
||||||
{
|
{
|
||||||
FTextureBuffer texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData);
|
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
|
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)
|
if (w <= 0 || h <= 0)
|
||||||
throw CVulkanError("Trying to create zero size texture");
|
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;
|
ImageBuilder imgbuilder;
|
||||||
imgbuilder.setFormat(format);
|
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);
|
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 = imgbuilder.create(fb->device);
|
||||||
mImage.Image->SetDebugName("VkHardwareTexture.mImage");
|
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));
|
fb->FrameDeleteList.Buffers.push_back(std::move(stagingBuffer));
|
||||||
|
|
||||||
mImage.GenerateMipmaps(cmdbuffer);
|
if (mipmap) mImage.GenerateMipmaps(cmdbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int VkHardwareTexture::GetMipLevels(int w, int h)
|
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)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,10 +374,6 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
|
||||||
int clampmode = state.mClampMode;
|
int clampmode = state.mClampMode;
|
||||||
int translation = state.mTranslation;
|
int translation = state.mTranslation;
|
||||||
|
|
||||||
auto remap = translation <= 0 ? nullptr : GPalette.TranslationToTable(translation);
|
|
||||||
if (remap)
|
|
||||||
translation = remap->Index;
|
|
||||||
|
|
||||||
clampmode = base->GetClampMode(clampmode);
|
clampmode = base->GetClampMode(clampmode);
|
||||||
|
|
||||||
for (auto& set : mDescriptorSets)
|
for (auto& set : mDescriptorSets)
|
||||||
|
@ -395,10 +394,23 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
|
||||||
MaterialLayerInfo *layer;
|
MaterialLayerInfo *layer;
|
||||||
auto systex = static_cast<VkHardwareTexture*>(GetLayer(0, state.mTranslation, &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);
|
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));
|
for (int i = 1; i < numLayers; i++)
|
||||||
update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout);
|
{
|
||||||
|
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();
|
auto dummyImage = fb->GetRenderPassManager()->GetNullTextureView();
|
||||||
|
|
|
@ -24,7 +24,7 @@ class VkHardwareTexture : public IHardwareTexture
|
||||||
{
|
{
|
||||||
friend class VkMaterial;
|
friend class VkMaterial;
|
||||||
public:
|
public:
|
||||||
VkHardwareTexture();
|
VkHardwareTexture(int numchannels);
|
||||||
~VkHardwareTexture();
|
~VkHardwareTexture();
|
||||||
|
|
||||||
static void ResetAll();
|
static void ResetAll();
|
||||||
|
@ -45,7 +45,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void CreateImage(FTexture *tex, int translation, int flags);
|
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 int GetMipLevels(int w, int h);
|
||||||
|
|
||||||
static VkHardwareTexture *First;
|
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())
|
if (!texture.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
FGameTexture* tex = TexMan.GetGameTexture(texture, !(flags & DI_DONTANIMATE));
|
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)
|
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 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(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 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 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 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);
|
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);
|
FTexture::SetSize(width, height);
|
||||||
Image.Resize(width * height * (format == Paletted ? 1 : 3));
|
Image.Resize(width * height * (format == Paletted ? 1 : 3));
|
||||||
memset(Image.Data(), 0, Image.Size());
|
memset(Image.Data(), 0, Image.Size());
|
||||||
CleanHardwareTextures();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimTexture::SetFrame(const uint8_t* palette, const void* data_)
|
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));
|
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);
|
static_cast<AnimTexture*>(tex[1]->GetTexture())->SetFrameSize(format, width, height);
|
||||||
tex[0]->SetSize(width, height);
|
tex[0]->SetSize(width, height);
|
||||||
tex[1]->SetSize(width, height);
|
tex[1]->SetSize(width, height);
|
||||||
|
tex[0]->CleanHardwareData();
|
||||||
|
tex[1]->CleanHardwareData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimTextures::SetFrame(const uint8_t* palette, const void* data)
|
void AnimTextures::SetFrame(const uint8_t* palette, const void* data)
|
||||||
{
|
{
|
||||||
active ^= 1;
|
active ^= 1;
|
||||||
static_cast<AnimTexture*>(tex[active]->GetTexture())->SetFrame(palette, data);
|
static_cast<AnimTexture*>(tex[active]->GetTexture())->SetFrame(palette, data);
|
||||||
|
tex[active]->CleanHardwareData();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
|
|
||||||
static IHardwareTexture* (*layercallback)(int layer, int translation);
|
static IHardwareTexture* (*layercallback)(int layer, int translation);
|
||||||
|
TArray<UserShaderDesc> usershaders;
|
||||||
|
|
||||||
void FMaterial::SetLayerCallback(IHardwareTexture* (*cb)(int layer, int translation))
|
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);
|
template <typename Polygon> Node* eliminateHoles(const Polygon& points, Node* outerNode);
|
||||||
void eliminateHole(Node* hole, Node* outerNode);
|
void eliminateHole(Node* hole, Node* outerNode);
|
||||||
Node* findHoleBridge(Node* hole, Node* outerNode);
|
Node* findHoleBridge(Node* hole, Node* outerNode);
|
||||||
|
bool sectorContainsSector(const Node* m, const Node* p);
|
||||||
void indexCurve(Node* start);
|
void indexCurve(Node* start);
|
||||||
Node* sortLinked(Node* list);
|
Node* sortLinked(Node* list);
|
||||||
int32_t zOrder(const double x_, const double y_);
|
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;
|
double area(const Node* p, const Node* q, const Node* r) const;
|
||||||
bool equals(const Node* p1, const Node* p2);
|
bool equals(const Node* p1, const Node* p2);
|
||||||
bool intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2);
|
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 intersectsPolygon(const Node* a, const Node* b);
|
||||||
bool locallyInside(const Node* a, const Node* b);
|
bool locallyInside(const Node* a, const Node* b);
|
||||||
bool middleInside(const Node* a, const Node* b);
|
bool middleInside(const Node* a, const Node* b);
|
||||||
|
@ -116,16 +119,18 @@ private:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
T* construct(Args&&... args) {
|
T* construct(Args&&... args) {
|
||||||
if (currentIndex >= blockSize) {
|
if (currentIndex >= blockSize) {
|
||||||
currentBlock = alloc.allocate(blockSize);
|
currentBlock = alloc_traits::allocate(alloc, blockSize);
|
||||||
allocations.emplace_back(currentBlock);
|
allocations.emplace_back(currentBlock);
|
||||||
currentIndex = 0;
|
currentIndex = 0;
|
||||||
}
|
}
|
||||||
T* object = ¤tBlock[currentIndex++];
|
T* object = ¤tBlock[currentIndex++];
|
||||||
alloc.construct(object, std::forward<Args>(args)...);
|
alloc_traits::construct(alloc, object, std::forward<Args>(args)...);
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
void reset(std::size_t newBlockSize) {
|
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();
|
allocations.clear();
|
||||||
blockSize = std::max<std::size_t>(1, newBlockSize);
|
blockSize = std::max<std::size_t>(1, newBlockSize);
|
||||||
currentBlock = nullptr;
|
currentBlock = nullptr;
|
||||||
|
@ -138,6 +143,7 @@ private:
|
||||||
std::size_t blockSize = 1;
|
std::size_t blockSize = 1;
|
||||||
std::vector<T*> allocations;
|
std::vector<T*> allocations;
|
||||||
Alloc alloc;
|
Alloc alloc;
|
||||||
|
typedef typename std::allocator_traits<Alloc> alloc_traits;
|
||||||
};
|
};
|
||||||
ObjectPool<Node> nodes;
|
ObjectPool<Node> nodes;
|
||||||
};
|
};
|
||||||
|
@ -165,7 +171,7 @@ void Earcut<N>::operator()(const Polygon& points) {
|
||||||
indices.reserve(len + points[0].size());
|
indices.reserve(len + points[0].size());
|
||||||
|
|
||||||
Node* outerNode = linkedList(points[0], true);
|
Node* outerNode = linkedList(points[0], true);
|
||||||
if (!outerNode) return;
|
if (!outerNode || outerNode->prev == outerNode->next) return;
|
||||||
|
|
||||||
if (points.size() > 1) outerNode = eliminateHoles(points, outerNode);
|
if (points.size() > 1) outerNode = eliminateHoles(points, outerNode);
|
||||||
|
|
||||||
|
@ -244,8 +250,7 @@ Earcut<N>::filterPoints(Node* start, Node* end) {
|
||||||
do {
|
do {
|
||||||
again = false;
|
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);
|
removeNode(p);
|
||||||
p = end = p->prev;
|
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
|
// if this didn't work, try curing all small self-intersections locally
|
||||||
else if (pass == 1) {
|
else if (pass == 1) {
|
||||||
ear = cureLocalIntersections(ear);
|
ear = cureLocalIntersections(filterPoints(ear));
|
||||||
earcutLinked(ear, 2);
|
earcutLinked(ear, 2);
|
||||||
|
|
||||||
// as a last resort, try splitting the remaining polygon into two
|
// as a last resort, try splitting the remaining polygon into two
|
||||||
|
@ -401,7 +406,7 @@ Earcut<N>::cureLocalIntersections(Node* start) {
|
||||||
p = p->next;
|
p = p->next;
|
||||||
} while (p != start);
|
} while (p != start);
|
||||||
|
|
||||||
return p;
|
return filterPoints(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try splitting polygon into two and triangulate them independently
|
// 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);
|
outerNode = findHoleBridge(hole, outerNode);
|
||||||
if (outerNode) {
|
if (outerNode) {
|
||||||
Node* b = splitPolygon(outerNode, hole);
|
Node* b = splitPolygon(outerNode, hole);
|
||||||
|
|
||||||
|
// filter out colinear points around cuts
|
||||||
|
filterPoints(outerNode, outerNode->next);
|
||||||
filterPoints(b, b->next);
|
filterPoints(b, b->next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -497,7 +505,7 @@ Earcut<N>::findHoleBridge(Node* hole, Node* outerNode) {
|
||||||
|
|
||||||
if (!m) return 0;
|
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;
|
// look for points inside the triangle of hole Vertex, segment intersection and endpoint;
|
||||||
// if there are no points found, we have a valid connection;
|
// 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 tanMin = std::numeric_limits<double>::infinity();
|
||||||
double tanCur = 0;
|
double tanCur = 0;
|
||||||
|
|
||||||
p = m->next;
|
p = m;
|
||||||
double mx = m->x;
|
double mx = m->x;
|
||||||
double my = m->y;
|
double my = m->y;
|
||||||
|
|
||||||
while (p != stop) {
|
do {
|
||||||
if (hx >= p->x && p->x >= mx && hx != p->x &&
|
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)) {
|
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
|
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;
|
m = p;
|
||||||
tanMin = tanCur;
|
tanMin = tanCur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
} while (p != stop);
|
||||||
|
|
||||||
return m;
|
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
|
// interlink polygon nodes in z-order
|
||||||
template <typename N>
|
template <typename N>
|
||||||
void Earcut<N>::indexCurve(Node* start) {
|
void Earcut<N>::indexCurve(Node* start) {
|
||||||
|
@ -644,7 +659,8 @@ Earcut<N>::getLeftmost(Node* start) {
|
||||||
Node* p = start;
|
Node* p = start;
|
||||||
Node* leftmost = start;
|
Node* leftmost = start;
|
||||||
do {
|
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;
|
p = p->next;
|
||||||
} while (p != start);
|
} 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)
|
// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
|
||||||
template <typename N>
|
template <typename N>
|
||||||
bool Earcut<N>::isValidDiagonal(Node* a, Node* b) {
|
bool Earcut<N>::isValidDiagonal(Node* a, Node* b) {
|
||||||
return a->next->i != b->i && a->prev->i != b->i && !intersectsPolygon(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);
|
((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
|
// signed area of a triangle
|
||||||
|
@ -681,10 +699,33 @@ bool Earcut<N>::equals(const Node* p1, const Node* p2) {
|
||||||
// check if two segments intersect
|
// check if two segments intersect
|
||||||
template <typename N>
|
template <typename N>
|
||||||
bool Earcut<N>::intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2) {
|
bool Earcut<N>::intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2) {
|
||||||
if ((equals(p1, q1) && equals(p2, q2)) ||
|
int o1 = sign(area(p1, q1, p2));
|
||||||
(equals(p1, q2) && equals(p2, q1))) return true;
|
int o2 = sign(area(p1, q1, q2));
|
||||||
return (area(p1, q1, p2) > 0) != (area(p1, q1, q2) > 0) &&
|
int o3 = sign(area(p2, q2, p1));
|
||||||
(area(p2, q2, p1) > 0) != (area(p2, q2, q1) > 0);
|
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
|
// check if a polygon diagonal intersects any polygon segments
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#define MAXWIDTH 12000
|
#define MAXWIDTH 12000
|
||||||
#define MAXHEIGHT 5000
|
#define MAXHEIGHT 5000
|
||||||
|
@ -101,3 +102,6 @@ enum EStateUseFlags
|
||||||
SUF_WEAPON = 4,
|
SUF_WEAPON = 4,
|
||||||
SUF_ITEM = 8,
|
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); }
|
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
|
#endif
|
||||||
|
|
|
@ -33,9 +33,7 @@ class VSMatrix {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
VSMatrix()
|
VSMatrix() = default;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
VSMatrix(int)
|
VSMatrix(int)
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,7 +54,6 @@ void AddLightAssociation(const char *actor, const char *frame, const char *light
|
||||||
void InitializeActorLights(TArray<FLightAssociation> &LightAssociations);
|
void InitializeActorLights(TArray<FLightAssociation> &LightAssociations);
|
||||||
void ParseColorization(FScanner& sc);
|
void ParseColorization(FScanner& sc);
|
||||||
|
|
||||||
TArray<UserShaderDesc> usershaders;
|
|
||||||
extern TDeletingArray<FLightDefaults *> LightDefaults;
|
extern TDeletingArray<FLightDefaults *> LightDefaults;
|
||||||
extern int AttenuationIsSet;
|
extern int AttenuationIsSet;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "hw_aabbtree.h"
|
#include "hw_aabbtree.h"
|
||||||
|
|
||||||
|
struct FLevelLocals;
|
||||||
|
|
||||||
// Axis aligned bounding box tree used for ray testing treelines.
|
// Axis aligned bounding box tree used for ray testing treelines.
|
||||||
class DoomLevelAABBTree : public hwrenderer::LevelAABBTree
|
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;
|
auto skybox = origin->texture[0] ? dynamic_cast<FSkyBox*>(origin->texture[0]->GetTexture()) : nullptr;
|
||||||
if (skybox)
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue