Skip to content

Commit

Permalink
Hook up texture loading
Browse files Browse the repository at this point in the history
  • Loading branch information
dpjudas committed Mar 24, 2024
1 parent e1fe465 commit a6e4290
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 30 deletions.
37 changes: 26 additions & 11 deletions src/framework/filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class FolderFileSystemSource : public IFileSystemSource
public:
FolderFileSystemSource(const FString& foldername)
{
Basepath = foldername;
ScanFolder(foldername.GetChars());
}

Expand All @@ -69,15 +70,15 @@ class FolderFileSystemSource : public IFileSystemSource

int CheckNumForFullName(const FString& fullname) override
{
auto it = FilenameKeyToIndex.find(fullname.GetChars());
if (it == FilenameKeyToIndex.end())
auto it = FullnameKeyToIndex.find(ToFullnameKey(fullname.GetChars()));
if (it == FullnameKeyToIndex.end())
return -1;
return (int)it->second;
}

int FileLength(int lump) override
{
int64_t size = File::open_existing(Filenames[lump])->size();
int64_t size = File::open_existing(FilePath::combine(Basepath, Filenames[lump]))->size();
// For safety. The filesystem API clearly wasn't designed to handle large files.
if (size >= 0x7fffffff) throw std::runtime_error("File is too big");
return (int)size;
Expand All @@ -86,7 +87,7 @@ class FolderFileSystemSource : public IFileSystemSource
FileData ReadFile(int lump) override
{
FileData data;
data.Buffer = File::read_all_bytes(Filenames[lump]);
data.Buffer = File::read_all_bytes(FilePath::combine(Basepath, Filenames[lump]));
return data;
}

Expand All @@ -95,26 +96,40 @@ class FolderFileSystemSource : public IFileSystemSource
return Filenames[lump].c_str();
}

void ScanFolder(const std::string& foldername, int depth = 0)
static std::string ToFullnameKey(std::string name)
{
for (char& c : name)
{
if (c == '\\')
c = '/';
if (c >= 'A' && c <= 'Z')
c = c - 'A' + 'a';
}
return name;
}

void ScanFolder(const std::string& foldername, const std::string& relativefoldername = {}, int depth = 0)
{
for (const std::string& filename : Directory::files(foldername))
std::string search = FilePath::combine(foldername, "*");
for (const std::string& filename : Directory::files(search))
{
std::string fullname = FilePath::combine(foldername, filename);
FilenameKeyToIndex[fullname] = Filenames.size();
std::string fullname = FilePath::combine(relativefoldername, filename);
FullnameKeyToIndex[ToFullnameKey(fullname)] = Filenames.size();
Filenames.push_back(fullname);
}

if (depth < 16)
{
for (const std::string& subfolder : Directory::folders(foldername))
for (const std::string& subfolder : Directory::folders(search))
{
ScanFolder(FilePath::combine(foldername, subfolder), depth + 1);
ScanFolder(FilePath::combine(foldername, subfolder), FilePath::combine(relativefoldername, subfolder), depth + 1);
}
}
}

std::string Basepath;
std::vector<std::string> Filenames;
std::map<std::string, size_t> FilenameKeyToIndex;
std::map<std::string, size_t> FullnameKeyToIndex;
};

/////////////////////////////////////////////////////////////////////////////
Expand Down
10 changes: 8 additions & 2 deletions src/framework/textureid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@ FTextureManager TexMan;

FGameTexture::FGameTexture(FString name) : Name(name)
{
// To do: improve this to support subfolders?
// To do: figure out what type of data we got here instead of assuming it is a png.

int lump = fileSystem.CheckNumForFullName(name);
if (lump < 0)
lump = fileSystem.CheckNumForFullName("textures/" + name + ".png");
if (lump < 0)
lump = fileSystem.CheckNumForFullName("flats/" + name + ".png");

if (lump < 0)
{
// Not found - should we mark it as invalid or use a dummy texture?
Expand All @@ -16,8 +24,6 @@ FGameTexture::FGameTexture(FString name) : Name(name)
}
else
{
// To do: figure out what type of data we got here instead of assuming it is a png.

FileData filedata = fileSystem.ReadFile(lump);
int result = decodePNG(Pixels, Width, Height, (const unsigned char*)filedata.GetMem(), fileSystem.FileLength(lump), true);
if (result == 0)
Expand Down
9 changes: 9 additions & 0 deletions src/framework/textureid.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,26 @@ class FGameTexture
bool isValid() const { return Valid; }
float GetDisplayWidth() const { return DisplayWidth; }
float GetDisplayHeight() const { return DisplayHeight; }

float GetScaleX() const { return ScaleX; }
float GetScaleY() const { return ScaleY; }

const void* GetImagePixels() const { return Pixels.data(); }
int GetImageWidth() const { return Width; }
int GetImageHeight() const { return Height; }

int GetTexelWidth() const { return GetImageWidth(); }
int GetTexelHeight() const { return GetImageHeight(); }

bool isHardwareCanvas() const { return false; }
bool useWorldPanning() const { return false; }

private:
FString Name;
bool Valid = true;
float DisplayWidth = 0.0f;
float DisplayHeight = 0.0f;
float ScaleX = 1.0f;
float ScaleY = 1.0f;

std::vector<unsigned char> Pixels;
Expand Down
13 changes: 13 additions & 0 deletions src/level/doomdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ struct IntSideDef
return TexMan.CheckForTexture(names[(int)part], ETextureType::Wall);
}

float GetTextureXOffset(WallPart part) { return 0.0f; }
float GetTextureXScale(WallPart part) { return 1.0f; }

float GetTextureYOffset(WallPart part) { return 0.0f; }
float GetTextureYScale(WallPart part) { return 1.0f; }

Expand All @@ -115,6 +118,16 @@ struct IntSideDef

FVector2 V1(const FLevel& level) const;
FVector2 V2(const FLevel& level) const;

float GetTexelLength(const FLevel& level) const
{
FVector2 v1 = V1(level);
FVector2 v2 = V2(level);
double dx = v2.X - v1.X;
double dy = v2.Y - v1.Y;
int len = (int)(g_sqrt(dx * dx + dy * dy) + 0.5f);
return (float)len;
}
};

struct MapLineDef
Expand Down
103 changes: 91 additions & 12 deletions src/lightmapper/doom_levelmesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ void DoomLevelMesh::CreateLineHorizonSurface(FLevel& doomMap, IntSideDef* side)
verts[3].z = v2Top;
AddWallVertices(surf, verts);

SetSideTextureUVs(surf, side, WallPart::TOP, v1Top, v1Bottom, v2Top, v2Bottom);
SetSideTextureUVs(doomMap, surf, side, WallPart::TOP, v1Top, v1Bottom, v2Top, v2Bottom);

Surfaces.Push(surf);
}
Expand Down Expand Up @@ -353,7 +353,7 @@ void DoomLevelMesh::CreateFrontWallSurface(FLevel& doomMap, IntSideDef* side)
surf.Texture = side->GetTexture(WallPart::MIDDLE);
AddWallVertices(surf, verts);

SetSideTextureUVs(surf, side, WallPart::TOP, v1Top, v1Bottom, v2Top, v2Bottom);
SetSideTextureUVs(doomMap, surf, side, WallPart::TOP, v1Top, v1Bottom, v2Top, v2Bottom);
AddSurfaceToTile(surf, doomMap, side->GetSampleDistance(WallPart::MIDDLE));

Surfaces.Push(surf);
Expand Down Expand Up @@ -433,7 +433,7 @@ void DoomLevelMesh::CreateMidWallSurface(FLevel& doomMap, IntSideDef* side)
surf.Plane.W = -surf.Plane.W;
}

SetSideTextureUVs(surf, side, WallPart::TOP, verts[2].z, verts[0].z, verts[3].z, verts[1].z);
SetSideTextureUVs(doomMap, surf, side, WallPart::TOP, verts[2].z, verts[0].z, verts[3].z, verts[1].z);
AddSurfaceToTile(surf, doomMap, side->GetSampleDistance(WallPart::MIDDLE));

Surfaces.Push(surf);
Expand Down Expand Up @@ -495,7 +495,7 @@ void DoomLevelMesh::Create3DFloorWallSurfaces(FLevel& doomMap, IntSideDef* side)
surf.Texture = xfloor->Line->sidedef[0]->GetTexture(WallPart::MIDDLE);

AddWallVertices(surf, verts);
SetSideTextureUVs(surf, side, WallPart::TOP, v1Top, v1Bottom, v2Top, v2Bottom);
SetSideTextureUVs(doomMap, surf, side, WallPart::TOP, v1Top, v1Bottom, v2Top, v2Bottom);
AddSurfaceToTile(surf, doomMap, side->GetSampleDistance(WallPart::MIDDLE));

Surfaces.Push(surf);
Expand Down Expand Up @@ -539,7 +539,7 @@ void DoomLevelMesh::CreateTopWallSurface(FLevel& doomMap, IntSideDef* side)
surf.Texture = side->GetTexture(WallPart::TOP);

AddWallVertices(surf, verts);
SetSideTextureUVs(surf, side, WallPart::TOP, v1Top, v1TopBack, v2Top, v2TopBack);
SetSideTextureUVs(doomMap, surf, side, WallPart::TOP, v1Top, v1TopBack, v2Top, v2TopBack);
AddSurfaceToTile(surf, doomMap, side->GetSampleDistance(WallPart::TOP));

Surfaces.Push(surf);
Expand Down Expand Up @@ -581,17 +581,97 @@ void DoomLevelMesh::CreateBottomWallSurface(FLevel& doomMap, IntSideDef* side)
surf.Texture = side->GetTexture(WallPart::BOTTOM);

AddWallVertices(surf, verts);
SetSideTextureUVs(surf, side, WallPart::BOTTOM, v1BottomBack, v1Bottom, v2BottomBack, v2Bottom);
SetSideTextureUVs(doomMap, surf, side, WallPart::BOTTOM, v1BottomBack, v1Bottom, v2BottomBack, v2Bottom);
AddSurfaceToTile(surf, doomMap, side->GetSampleDistance(WallPart::BOTTOM));

Surfaces.Push(surf);
}

void DoomLevelMesh::SetSideTextureUVs(DoomLevelMeshSurface& surface, IntSideDef* side, WallPart texpart, float v1TopZ, float v1BottomZ, float v2TopZ, float v2BottomZ)
struct FTexCoordInfo
{
int mRenderWidth;
int mRenderHeight;
int mWidth;
FVector2 mScale;
FVector2 mTempScale;
bool mWorldPanning;

float FloatToTexU(float v) const { return v / mRenderWidth; }
float FloatToTexV(float v) const { return v / mRenderHeight; }

float RowOffset(float rowoffset) const
{
float scale = fabsf(mScale.Y);
if (scale == 1.f || mWorldPanning) return rowoffset;
else return rowoffset / scale;
}

float TextureOffset(float textureoffset) const
{
float scale = fabsf(mScale.X);
if (scale == 1.f || mWorldPanning) return textureoffset;
else return textureoffset / scale;
}

float TextureAdjustWidth() const
{
if (mWorldPanning)
{
float tscale = fabsf(mTempScale.X);
if (tscale == 1.f) return (float)mRenderWidth;
else return mWidth / fabsf(tscale);
}
else return (float)mWidth;
}

void GetFromTexture(FGameTexture* tex, float x, float y, bool forceworldpanning)
{
if (x == 1.f)
{
mRenderWidth = xs_RoundToInt(tex->GetDisplayWidth());
mScale.X = tex->GetScaleX();
mTempScale.X = 1.f;
}
else
{
float scale_x = x * tex->GetScaleX();
mRenderWidth = xs_CeilToInt(tex->GetTexelWidth() / scale_x);
mScale.X = scale_x;
mTempScale.X = x;
}

if (y == 1.f)
{
mRenderHeight = xs_RoundToInt(tex->GetDisplayHeight());
mScale.Y = tex->GetScaleY();
mTempScale.Y = 1.f;
}
else
{
float scale_y = y * tex->GetScaleY();
mRenderHeight = xs_CeilToInt(tex->GetTexelHeight() / scale_y);
mScale.Y = scale_y;
mTempScale.Y = y;
}
if (tex->isHardwareCanvas())
{
mScale.Y = -mScale.Y;
mRenderHeight = -mRenderHeight;
}
mWorldPanning = tex->useWorldPanning() || forceworldpanning;
mWidth = tex->GetTexelWidth();
}
};

static void GetTexCoordInfo(FGameTexture* tex, FTexCoordInfo* tci, IntSideDef* side, WallPart texpos)
{
tci->GetFromTexture(tex, (float)side->GetTextureXScale(texpos), (float)side->GetTextureYScale(texpos), false/*!!(side->GetLevel()->flags3 & LEVEL3_FORCEWORLDPANNING)*/);
}

void DoomLevelMesh::SetSideTextureUVs(FLevel& doomMap, DoomLevelMeshSurface& surface, IntSideDef* side, WallPart texpart, float v1TopZ, float v1BottomZ, float v2TopZ, float v2BottomZ)
{
FFlatVertex* verts = &Mesh.Vertices[surface.MeshLocation.StartVertIndex];

#if 0
if (surface.Texture.isValid())
{
const auto gtxt = TexMan.GetGameTexture(surface.Texture);
Expand All @@ -600,24 +680,23 @@ void DoomLevelMesh::SetSideTextureUVs(DoomLevelMeshSurface& surface, IntSideDef*
GetTexCoordInfo(gtxt, &tci, side, texpart);

float startU = tci.FloatToTexU(tci.TextureOffset((float)side->GetTextureXOffset(texpart)) + tci.TextureOffset((float)side->GetTextureXOffset(texpart)));
float endU = startU + tci.FloatToTexU(side->TexelLength);
float endU = startU + tci.FloatToTexU(side->GetTexelLength(doomMap));

verts[0].u = startU;
verts[1].u = endU;
verts[2].u = startU;
verts[3].u = endU;

// To do: the ceiling version is apparently used in some situation related to 3d floors (rover->top.isceiling)
//float offset = tci.RowOffset((float)side->GetTextureYOffset(texpart)) + tci.RowOffset((float)side->GetTextureYOffset(texpart)) + (float)side->sector->GetPlaneTexZ(PLANE_CEILING);
float offset = tci.RowOffset((float)side->GetTextureYOffset(texpart)) + tci.RowOffset((float)side->GetTextureYOffset(texpart)) + (float)side->sector->GetPlaneTexZ(PLANE_FLOOR);
//float offset = tci.RowOffset((float)side->GetTextureYOffset(texpart)) + tci.RowOffset((float)side->GetTextureYOffset(texpart)) + (float)doomMap.Sectors[side->sector].ceilingTexZ;
float offset = tci.RowOffset((float)side->GetTextureYOffset(texpart)) + tci.RowOffset((float)side->GetTextureYOffset(texpart)) + (float)doomMap.Sectors[side->sector].floorTexZ;

verts[0].v = tci.FloatToTexV(offset - v1BottomZ);
verts[1].v = tci.FloatToTexV(offset - v2BottomZ);
verts[2].v = tci.FloatToTexV(offset - v1TopZ);
verts[3].v = tci.FloatToTexV(offset - v2TopZ);
}
else
#endif
{
for (int i = 0; i < 4; i++)
{
Expand Down
2 changes: 1 addition & 1 deletion src/lightmapper/doom_levelmesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class DoomLevelMesh : public LevelMesh
void CreateTopWallSurface(FLevel& doomMap, IntSideDef* side);
void CreateBottomWallSurface(FLevel& doomMap, IntSideDef* side);
void AddWallVertices(DoomLevelMeshSurface& surf, FFlatVertex* verts);
void SetSideTextureUVs(DoomLevelMeshSurface& surface, IntSideDef* side, WallPart texpart, float v1TopZ, float v1BottomZ, float v2TopZ, float v2BottomZ);
void SetSideTextureUVs(FLevel& doomMap, DoomLevelMeshSurface& surface, IntSideDef* side, WallPart texpart, float v1TopZ, float v1BottomZ, float v2TopZ, float v2BottomZ);

void CreateFloorSurface(FLevel& doomMap, MapSubsectorEx* sub, IntSector* sector, X3DFloor* controlSector, int typeIndex);
void CreateCeilingSurface(FLevel& doomMap, MapSubsectorEx* sub, IntSector* sector, X3DFloor* controlSector, int typeIndex);
Expand Down
Loading

0 comments on commit a6e4290

Please sign in to comment.