- reworked the multipatch texture builder to reuse the FImageTexture objects.

This commit is contained in:
Christoph Oelckers 2020-04-18 21:04:55 +02:00
parent 59cd049b77
commit ef8e7a4944
13 changed files with 104 additions and 99 deletions

View file

@ -381,7 +381,7 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
void FFont::ReadSheetFont(TArray<FolderEntry> &folderdata, int width, int height, const DVector2 &Scale)
{
// all valid lumps must be named with a hex number that represents the Unicode character index for its first character,
TArray<TexPart> part(1, true);
TArray<TexPartBuild> part(1, true);
TMap<int, FGameTexture*> charMap;
int minchar = INT_MAX;
int maxchar = INT_MIN;
@ -408,13 +408,10 @@ void FFont::ReadSheetFont(TArray<FolderEntry> &folderdata, int width, int height
{
part[0].OriginX = -width * x;
part[0].OriginY = -height * y;
part[0].Image = tex->GetTexture()->GetImage();
part[0].TexImage = static_cast<FImageTexture*>(tex->GetTexture());
FMultiPatchTexture *image = new FMultiPatchTexture(width, height, part, false, false);
FImageTexture *tex = new FImageTexture(image);
auto gtex = MakeGameTexture(tex, nullptr, ETextureType::FontChar);
tex->bMasked = true;
tex->bTranslucent = -1;
tex->SourceLump = -1; // We do not really care.
gtex->SetWorldPanning(true);
gtex->SetOffsets(0, 0, 0);
gtex->SetOffsets(1, 0, 0);

View file

@ -46,15 +46,19 @@
//
//==========================================================================
FMultiPatchTexture::FMultiPatchTexture(int w, int h, const TArray<TexPart> &parts, bool complex, bool textual)
FMultiPatchTexture::FMultiPatchTexture(int w, int h, const TArray<TexPartBuild> &parts, bool complex, bool textual)
{
Width = w;
Height = h;
bComplex = complex;
bTextual = textual;
bTextual = textual;
Parts = (TexPart*)ImageArena.Alloc(sizeof(TexPart) * parts.Size());
NumParts = parts.Size();
memcpy(Parts, parts.Data(), sizeof(TexPart) * parts.Size());
for (unsigned i = 0; i < parts.Size(); i++)
{
Parts[i].Image = parts[i].TexImage->GetImage();
}
bUseGamePalette = false;
if (!bComplex)

View file

@ -5,6 +5,7 @@
#include "vectors.h"
#include "bitmap.h"
#include "image.h"
#include "textures.h"
class FImageTexture;
class FTextureManager;
@ -27,6 +28,18 @@ struct TexPart
uint8_t op = OP_COPY;
};
struct TexPartBuild
{
FRemapTable* Translation = nullptr;
FImageTexture *TexImage = nullptr;
PalEntry Blend = 0;
blend_t Alpha = FRACUNIT;
int16_t OriginX = 0;
int16_t OriginY = 0;
uint8_t Rotate = 0;
uint8_t op = OP_COPY;
};
//==========================================================================
@ -40,7 +53,7 @@ class FMultiPatchTexture : public FImageSource
friend class FTexture;
friend class FGameTexture;
public:
FMultiPatchTexture(int w, int h, const TArray<TexPart> &parts, bool complex, bool textual);
FMultiPatchTexture(int w, int h, const TArray<TexPartBuild> &parts, bool complex, bool textual);
int GetNumParts() const { return NumParts; }
// Query some needed info for texture hack support.
bool SupportRemap0() override;
@ -79,7 +92,7 @@ struct TexInit
{
FString TexName;
ETextureType UseType = ETextureType::Null;
FTexture *Texture = nullptr;
FImageTexture *Texture = nullptr;
bool Silent = false;
bool HasLine = false;
bool UseOffsets = false;
@ -97,7 +110,7 @@ struct FPatchLookup;
struct BuildInfo
{
FString Name;
TArray<TexPart> Parts;
TArray<TexPartBuild> Parts;
TArray<TexInit> Inits;
int Width = 0;
int Height = 0;
@ -109,7 +122,6 @@ struct BuildInfo
bool bNoDecals = false;
int LeftOffset[2] = {};
int TopOffset[2] = {};
FImageTexture* itex = nullptr;
FGameTexture *texture = nullptr;
void swap(BuildInfo &other)
@ -129,7 +141,6 @@ struct BuildInfo
std::swap(LeftOffset[1], other.LeftOffset[1]);
std::swap(TopOffset[0], other.TopOffset[0]);
std::swap(TopOffset[1], other.TopOffset[1]);
std::swap(itex, other.itex);
std::swap(texture, other.texture);
}
};
@ -140,16 +151,17 @@ class FMultipatchTextureBuilder
{
FTextureManager &TexMan;
TArray<BuildInfo> BuiltTextures;
TMap<FTexture*, bool> complex;
TMap<FGameTexture*, bool> complex;
void(*progressFunc)();
void(*checkForHacks)(BuildInfo&);
void MakeTexture(BuildInfo &buildinfo, ETextureType usetype);
void AddImageToTexture(FImageTexture* tex, BuildInfo& buildinfo);
void BuildTexture(const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflumpnum, ETextureType usetyoe);
void AddTexturesLump(const void *lumpdata, int lumpsize, int deflumpnum, int patcheslump, int firstdup, bool texture1);
void ParsePatch(FScanner &sc, BuildInfo &info, TexPart &part, TexInit &init);
void ParsePatch(FScanner &sc, BuildInfo &info, TexPartBuild &part, TexInit &init);
void ResolvePatches(BuildInfo &buildinfo);
public:

View file

@ -623,6 +623,8 @@ FPNGFileTexture::FPNGFileTexture (FileReader &lump, int width, int height, uint8
{
Width = width;
Height = height;
Masked = false;
bTranslucent = false;
fr = std::move(lump);
}

View file

@ -63,7 +63,7 @@ void FImageTexture::SetFromImage()
Width = img->GetWidth();
Height = img->GetHeight();
bMasked = img->bMasked;
Masked = img->bMasked;
bTranslucent = img->bTranslucent;
}
//===========================================================================

View file

@ -57,7 +57,6 @@
#endif
//--------------------------------------------------------------------------
//
// Data structures for the TEXTUREx lumps
@ -85,7 +84,7 @@ struct mappatch_t
struct maptexture_t
{
uint8_t name[8];
uint16_t Flags; // [RH] Was unused
uint16_t Flags; // [RH] Was unused
uint8_t ScaleX; // [RH] Scaling (8 is normal)
uint8_t ScaleY; // [RH] Same as above
int16_t width;
@ -113,7 +112,7 @@ struct strifemappatch_t
struct strifemaptexture_t
{
uint8_t name[8];
uint16_t Flags; // [RH] Was unused
uint16_t Flags; // [RH] Was unused
uint8_t ScaleX; // [RH] Scaling (8 is normal)
uint8_t ScaleY; // [RH] Same as above
int16_t width;
@ -137,22 +136,23 @@ struct FPatchLookup
void FMultipatchTextureBuilder::MakeTexture(BuildInfo &buildinfo, ETextureType usetype)
{
FImageTexture *tex = new FImageTexture(nullptr);
tex->SetSize(buildinfo.Width, buildinfo.Height);
tex->bMasked = true; // we do not really know yet.
tex->bTranslucent = -1;
tex->SourceLump = buildinfo.DefinitionLump;
buildinfo.itex = tex;
buildinfo.texture = MakeGameTexture(tex, buildinfo.Name, usetype);
buildinfo.texture = new FGameTexture(nullptr, buildinfo.Name);
buildinfo.texture->SetUseType(usetype);
TexMan.AddGameTexture(buildinfo.texture);
}
void FMultipatchTextureBuilder::AddImageToTexture(FImageTexture *tex, BuildInfo& buildinfo)
{
buildinfo.texture->Setup(tex);
buildinfo.texture->SetOffsets(0, buildinfo.LeftOffset[0], buildinfo.TopOffset[0]);
buildinfo.texture->SetOffsets(1, buildinfo.LeftOffset[1], buildinfo.TopOffset[1]);
buildinfo.texture->SetScale((float)buildinfo.Scale.X, (float)buildinfo.Scale.X);
buildinfo.texture->SetWorldPanning(buildinfo.bWorldPanning);
buildinfo.texture->SetNoDecals(buildinfo.bNoDecals);
TexMan.AddGameTexture(buildinfo.texture);
calcShouldUpscale(buildinfo.texture); // calculate this once at insertion
}
//==========================================================================
//
// The reader for TEXTUREx
@ -235,7 +235,7 @@ void FMultipatchTextureBuilder::BuildTexture(const void *texdef, FPatchLookup *p
}
buildinfo.Parts[i].OriginX = LittleShort(mpatch.d->originx);
buildinfo.Parts[i].OriginY = LittleShort(mpatch.d->originy);
buildinfo.Parts[i].Image = nullptr;
buildinfo.Parts[i].TexImage = nullptr;
buildinfo.Inits[i].TexName = patchlookup[LittleShort(mpatch.d->patch)].Name;
buildinfo.Inits[i].UseType = ETextureType::WallPatch;
if (strife)
@ -417,7 +417,7 @@ void FMultipatchTextureBuilder::AddTexturesLumps(int lump1, int lump2, int patch
//
//==========================================================================
void FMultipatchTextureBuilder::ParsePatch(FScanner &sc, BuildInfo &info, TexPart & part, TexInit &init)
void FMultipatchTextureBuilder::ParsePatch(FScanner &sc, BuildInfo &info, TexPartBuild & part, TexInit &init)
{
FString patchname;
int Mirror = 0;
@ -669,7 +669,7 @@ void FMultipatchTextureBuilder::ParseTexture(FScanner &sc, ETextureType UseType)
}
else if (sc.Compare("Patch"))
{
TexPart part;
TexPartBuild part;
TexInit init;
ParsePatch(sc, buildinfo, part, init);
if (init.TexName.IsNotEmpty())
@ -681,12 +681,12 @@ void FMultipatchTextureBuilder::ParseTexture(FScanner &sc, ETextureType UseType)
init.sc = sc;
buildinfo.Inits.Push(init);
}
part.Image = nullptr;
part.TexImage = nullptr;
part.Translation = nullptr;
}
else if (sc.Compare("Sprite"))
{
TexPart part;
TexPartBuild part;
TexInit init;
ParsePatch(sc, buildinfo, part, init);
if (init.TexName.IsNotEmpty())
@ -698,12 +698,12 @@ void FMultipatchTextureBuilder::ParseTexture(FScanner &sc, ETextureType UseType)
init.sc = sc;
buildinfo.Inits.Push(init);
}
part.Image = nullptr;
part.TexImage = nullptr;
part.Translation = nullptr;
}
else if (sc.Compare("Graphic"))
{
TexPart part;
TexPartBuild part;
TexInit init;
ParsePatch(sc, buildinfo, part, init);
if (init.TexName.IsNotEmpty())
@ -715,7 +715,7 @@ void FMultipatchTextureBuilder::ParseTexture(FScanner &sc, ETextureType UseType)
init.sc = sc;
buildinfo.Inits.Push(init);
}
part.Image = nullptr;
part.TexImage = nullptr;
part.Translation = nullptr;
}
else if (sc.Compare("Offset"))
@ -812,12 +812,12 @@ void FMultipatchTextureBuilder::ResolvePatches(BuildInfo &buildinfo)
{
FGameTexture *tex = TexMan.GetGameTexture(texno);
if (tex != nullptr && tex->isValid())
if (tex != nullptr && tex->isValid() && dynamic_cast<FImageTexture*>(tex->GetTexture()))
{
//We cannot set the image source yet. First all textures need to be resolved.
buildinfo.Inits[i].Texture = tex->GetTexture();
bool iscomplex = !!complex.CheckKey(tex->GetTexture());
if (iscomplex) complex.Insert(buildinfo.itex, true);
buildinfo.Inits[i].Texture = static_cast<FImageTexture*>(tex->GetTexture());
bool iscomplex = !!complex.CheckKey(tex);
if (iscomplex) complex.Insert(buildinfo.texture, true);
buildinfo.bComplex |= iscomplex;
if (buildinfo.Inits[i].UseOffsets)
{
@ -876,12 +876,12 @@ void FMultipatchTextureBuilder::ResolveAllPatches()
for (unsigned j = 0; j < buildinfo.Inits.Size(); j++)
{
if (buildinfo.Parts[j].Image == nullptr)
if (buildinfo.Parts[j].TexImage == nullptr)
{
auto image = buildinfo.Inits[j].Texture->GetImage();
if (image != nullptr)
auto image = buildinfo.Inits[j].Texture;
if (image->GetImage() != nullptr)
{
buildinfo.Parts[j].Image = image;
buildinfo.Parts[j].TexImage = image;
donesomething = true;
}
else hasEmpty = true;
@ -896,19 +896,21 @@ void FMultipatchTextureBuilder::ResolveAllPatches()
if (buildinfo.Parts.Size() == 1)
{
if (buildinfo.Parts[0].OriginX == 0 && buildinfo.Parts[0].OriginY == 0 &&
buildinfo.Parts[0].Image->GetWidth() == buildinfo.Width &&
buildinfo.Parts[0].Image->GetHeight() == buildinfo.Height &&
buildinfo.Parts[0].TexImage->GetWidth() == buildinfo.Width &&
buildinfo.Parts[0].TexImage->GetHeight() == buildinfo.Height &&
buildinfo.Parts[0].Rotate == 0 &&
!buildinfo.bComplex)
{
buildinfo.itex->SetImage(buildinfo.Parts[0].Image);
AddImageToTexture(buildinfo.Parts[0].TexImage, buildinfo);
buildinfo.texture->Setup(buildinfo.Parts[0].TexImage);
done = true;
}
}
if (!done)
{
auto img = new FMultiPatchTexture(buildinfo.Width, buildinfo.Height, buildinfo.Parts, buildinfo.bComplex, buildinfo.textual);
buildinfo.itex->SetImage(img);
auto itex = new FImageTexture(img);
AddImageToTexture(itex, buildinfo);
}
BuiltTextures.Delete(i);

View file

@ -59,6 +59,5 @@ void FSkyBox::SetSize()
if (previous && previous->GetTexture()->GetImage())
{
SetImage(previous->GetTexture()->GetImage());
SetFromImage();
}
}

View file

@ -89,12 +89,8 @@ FTexture * FTexture::CreateTexture(int lumpnum, bool allowflats)
//==========================================================================
FTexture::FTexture (int lumpnum)
:
SourceLump(lumpnum),
bNoRemap0(false), bMasked(true), bAlphaTexture(false), bHasCanvas(false),
Rotations(0xFFFF), SkyOffset(0), Width(0), Height(0)
: SourceLump(lumpnum), bHasCanvas(false)
{
bNoCompress = false;
bTranslucent = -1;
}
@ -188,7 +184,6 @@ void FGameTexture::AddAutoMaterials()
auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny);
if (bmtex != nullptr)
{
bmtex->GetTexture()->bMasked = false;
this->*(layer.pointer) = bmtex->GetTexture();
}
}
@ -471,10 +466,10 @@ bool FTexture::SmoothEdges(unsigned char * buffer, int w, int h)
bool FTexture::ProcessData(unsigned char * buffer, int w, int h, bool ispatch)
{
if (bMasked)
if (Masked)
{
bMasked = SmoothEdges(buffer, w, h);
if (bMasked && !ispatch) FindHoles(buffer, w, h);
Masked = SmoothEdges(buffer, w, h);
if (Masked && !ispatch) FindHoles(buffer, w, h);
}
return true;
}
@ -557,15 +552,8 @@ FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags)
bool FTexture::DetermineTranslucency()
{
if (!bHasCanvas)
{
// This will calculate all we need, so just discard the result.
CreateTexBuffer(0);
}
else
{
bTranslucent = 0;
}
// This will calculate all we need, so just discard the result.
CreateTexBuffer(0);
return !!bTranslucent;
}
@ -930,15 +918,21 @@ FWrapperTexture::FWrapperTexture(int w, int h, int bits)
Width = w;
Height = h;
Format = bits;
bNoCompress = true;
//bNoCompress = true;
auto hwtex = CreateHardwareTexture();
// todo: Initialize here.
SystemTextures.AddHardwareTexture(0, false, hwtex);
}
FGameTexture::FGameTexture(FTexture* wrap, const char *name) : Base(wrap), Name(name)
FGameTexture::FGameTexture(FTexture* wrap, const char* name) : Name(name)
{
if (wrap) Setup(wrap);
}
void FGameTexture::Setup(FTexture *wrap)
{
Base = wrap;
id.SetInvalid();
TexelWidth = Base->GetWidth();
DisplayWidth = (float)TexelWidth;

View file

@ -383,8 +383,11 @@ FTextureID FTextureManager::AddGameTexture (FGameTexture *texture, bool addtohas
if (texture == NULL) return FTextureID(-1);
// Later textures take precedence over earlier ones
calcShouldUpscale(texture); // calculate this once at insertion
if (texture->GetTexture())
{
// Later textures take precedence over earlier ones
calcShouldUpscale(texture); // calculate this once at insertion
}
// Textures without name can't be looked for
if (addtohash && texture->GetName().IsNotEmpty())
@ -1268,9 +1271,10 @@ FTextureID FTextureManager::GetFrontSkyLayer(FTextureID texid)
// Set this up so that it serializes to the same info as the base texture - this is needed to restore it on load.
// But do not link the new texture into the hash chain!
auto FrontSkyLayer = MakeGameTexture(new FImageTexture(image), tex->GetName(), ETextureType::Wall);
auto itex = new FImageTexture(image);
itex->SetNoRemap0();
auto FrontSkyLayer = MakeGameTexture(itex, tex->GetName(), ETextureType::Wall);
FrontSkyLayer->SetUseType(tex->GetUseType());
FrontSkyLayer->GetTexture()->bNoRemap0 = true;
texid = TexMan.AddGameTexture(FrontSkyLayer, false);
Textures[texidx].FrontSkyLayer = texid.GetIndex();
Textures[texid.GetIndex()].FrontSkyLayer = texid.GetIndex(); // also let it refer to itself as its front sky layer, in case for repeated InitSkyMap calls.

View file

@ -240,28 +240,18 @@ struct SpritePositioningInfo
class FTexture : public RefCountedBase
{
friend class FGameTexture; // only for the porting work
friend class FTexture;
friend struct FTexCoordInfo;
friend class FMultipatchTextureBuilder;
friend class FMaterial;
friend class FFont;
protected:
uint16_t Width, Height;
int SourceLump;
FHardwareTextureContainer SystemTextures;
uint8_t bNoRemap0 : 1; // Do not remap color 0 (used by front layer of parallax skies)
uint8_t bNoCompress : 1;
uint8_t bMasked : 1; // Texture (might) have holes
uint8_t bAlphaTexture : 1; // Texture is an alpha channel without color information
uint8_t bHasCanvas : 1; // Texture is based off FCanvasTexture
int8_t bTranslucent : 2;
FloatRect* areas = nullptr;
int areacount = 0;
int SourceLump;
uint16_t Width = 0, Height = 0;
bool Masked = false; // Texture (might) have holes
bool bHasCanvas = false;
int8_t bTranslucent = -1;
int8_t areacount = 0; // this is capped at 4 sections.
public:
@ -277,7 +267,6 @@ public:
bool isHardwareCanvas() const { return bHasCanvas; } // There's two here so that this can deal with software canvases in the hardware renderer later.
bool isCanvas() const { return bHasCanvas; }
bool isMasked() const { return bMasked; }
int GetSourceLump() { return SourceLump; } // needed by the scripted GetName method.
bool FindHoles(const unsigned char * buffer, int w, int h);
@ -338,9 +327,7 @@ public:
Width = width;
Height = height;
bMasked = false;
bHasCanvas = true;
bTranslucent = false;
aspectRatio = (float)width / height;
}
@ -380,6 +367,7 @@ public:
class FImageTexture : public FTexture
{
FImageSource* mImage;
bool bNoRemap0;
protected:
void SetFromImage();
public:
@ -389,7 +377,9 @@ public:
void SetImage(FImageSource* img) // This is only for the multipatch texture builder!
{
mImage = img;
SetFromImage();
}
void SetNoRemap0() { bNoRemap0 = true; }
FImageSource* GetImage() const override { return mImage; }
FBitmap GetBgraBitmap(const PalEntry* p, int* trans) override;
@ -494,13 +484,14 @@ class FGameTexture
uint16_t GlowHeight;
PalEntry GlowColor = 0;
int16_t SkyOffset;
uint16_t Rotations;
int16_t SkyOffset = 0;
uint16_t Rotations = 0xffff;
public:
FGameTexture(FTexture* wrap, const char *name);
~FGameTexture();
void Setup(FTexture* wrap);
FTextureID GetID() const { return id; }
void SetID(FTextureID newid) { id = newid; } // should only be called by the texture manager
const FString& GetName() const { return Name; }
@ -545,7 +536,7 @@ public:
bool isValid() const { return UseType != ETextureType::Null; }
int isWarped() { return warped; }
void SetWarpStyle(int style) { warped = style; }
bool isMasked() { return Base->isMasked(); }
bool isMasked() { return Base->Masked; }
bool isHardwareCanvas() const { return Base->isHardwareCanvas(); } // There's two here so that this can deal with software canvases in the hardware renderer later.
bool isSoftwareCanvas() const { return Base->isCanvas(); }

View file

@ -2674,7 +2674,7 @@ static void CheckForHacks(BuildInfo& buildinfo)
buildinfo.Parts.Size() == 1)
{
// This must alter the size of both the texture image and the game texture.
buildinfo.Height = buildinfo.Parts[0].Image->GetHeight();
buildinfo.Height = buildinfo.Parts[0].TexImage->GetHeight();
buildinfo.texture->GetTexture()->SetSize(buildinfo.texture->GetTexelWidth(), buildinfo.Height);
buildinfo.texture->SetSize(buildinfo.texture->GetTexelWidth(), buildinfo.Height);
return;

View file

@ -276,7 +276,7 @@ FSoftwareTextureSpan **FSoftwareTexture::CreateSpans (const T *pixels)
{
FSoftwareTextureSpan **spans, *span;
if (!mSource->isMasked())
if (!mTexture->isMasked())
{ // Texture does not have holes, so it can use a simpler span structure
spans = (FSoftwareTextureSpan **)M_Malloc (sizeof(FSoftwareTextureSpan*)*GetPhysicalWidth() + sizeof(FSoftwareTextureSpan)*2);
span = (FSoftwareTextureSpan *)&spans[GetPhysicalWidth()];

View file

@ -53,7 +53,7 @@ public:
bool isMasked()
{
return mSource->isMasked();
return mTexture->isMasked();
}
uint16_t GetRotations() const