- move allocBlocks to LightmapTexture

This commit is contained in:
Magnus Norddahl 2018-12-31 17:23:54 +01:00
parent 79d0b257e1
commit d03ded7f94
2 changed files with 90 additions and 102 deletions

View file

@ -54,78 +54,6 @@ LightmapBuilder::~LightmapBuilder()
{ {
} }
void LightmapBuilder::NewTexture()
{
numTextures++;
allocBlocks.push_back(std::vector<int>(textureWidth));
textures.push_back(std::make_unique<LightmapTexture>(textureWidth, textureHeight));
}
// Determines where to map a new block on to the lightmap texture
bool LightmapBuilder::MakeRoomForBlock(const int width, const int height, int *x, int *y, int *num)
{
int i;
int j;
int k;
int bestRow1;
int bestRow2;
*num = -1;
if (allocBlocks.empty())
{
return false;
}
for (k = 0; k < numTextures; ++k)
{
bestRow1 = textureHeight;
for (i = 0; i <= textureWidth - width; i++)
{
bestRow2 = 0;
for (j = 0; j < width; j++)
{
if (allocBlocks[k][i + j] >= bestRow1)
{
break;
}
if (allocBlocks[k][i + j] > bestRow2)
{
bestRow2 = allocBlocks[k][i + j];
}
}
// found a free block
if (j == width)
{
*x = i;
*y = bestRow1 = bestRow2;
}
}
if (bestRow1 + height > textureHeight)
{
// no room
continue;
}
for (i = 0; i < width; i++)
{
// store row offset
allocBlocks[k][*x + i] = bestRow1 + height;
}
*num = k;
return true;
}
return false;
}
BBox LightmapBuilder::GetBoundsFromSurface(const Surface *surface) BBox LightmapBuilder::GetBoundsFromSurface(const Surface *surface)
{ {
Vec3 low(M_INFINITY, M_INFINITY, M_INFINITY); Vec3 low(M_INFINITY, M_INFINITY, M_INFINITY);
@ -477,28 +405,7 @@ void LightmapBuilder::FinishSurface(Surface *surface)
else else
{ {
int x = 0, y = 0; int x = 0, y = 0;
int width = surface->lightmapDims[0]; uint16_t *currentTexture = AllocTextureRoom(surface, &x, &y);
int height = surface->lightmapDims[1];
std::unique_lock<std::mutex> lock(mutex);
// now that we know the width and height of this block, see if we got
// room for it in the light map texture. if not, then we must allocate
// a new texture
if (!MakeRoomForBlock(width, height, &x, &y, &surface->lightmapNum))
{
// allocate a new texture for this block
NewTexture();
if (!MakeRoomForBlock(width, height, &x, &y, &surface->lightmapNum))
{
throw std::runtime_error("Lightmap allocation failed");
}
}
uint16_t *currentTexture = textures[surface->lightmapNum]->Pixels();
lock.unlock();
// calculate texture coordinates // calculate texture coordinates
for (int i = 0; i < surface->numVerts; i++) for (int i = 0; i < surface->numVerts; i++)
@ -528,6 +435,34 @@ void LightmapBuilder::FinishSurface(Surface *surface)
} }
} }
uint16_t *LightmapBuilder::AllocTextureRoom(Surface *surface, int *x, int *y)
{
int width = surface->lightmapDims[0];
int height = surface->lightmapDims[1];
int numTextures = textures.size();
int k;
for (k = 0; k < numTextures; ++k)
{
if (textures[k]->MakeRoomForBlock(width, height, x, y))
{
break;
}
}
if (k == numTextures)
{
textures.push_back(std::make_unique<LightmapTexture>(textureWidth, textureHeight));
if (!textures[k]->MakeRoomForBlock(width, height, x, y))
{
throw std::runtime_error("Lightmap allocation failed");
}
}
surface->lightmapNum = k;
return textures[surface->lightmapNum]->Pixels();
}
static float RadicalInverse_VdC(uint32_t bits) static float RadicalInverse_VdC(uint32_t bits)
{ {
bits = (bits << 16u) | (bits >> 16u); bits = (bits << 16u) | (bits >> 16u);
@ -1033,3 +968,56 @@ void LightmapBuilder::AddLightmapLump(FWadWriter &wadFile)
wadFile.StartWritingLump("LIGHTMAP"); wadFile.StartWritingLump("LIGHTMAP");
zout.Write(buffer.data(), lumpFile.BufferAt() - lumpFile.Buffer()); zout.Write(buffer.data(), lumpFile.BufferAt() - lumpFile.Buffer());
} }
/////////////////////////////////////////////////////////////////////////////
LightmapTexture::LightmapTexture(int width, int height) : textureWidth(width), textureHeight(height)
{
mPixels.resize(width * height * 3);
allocBlocks.resize(width);
}
bool LightmapTexture::MakeRoomForBlock(const int width, const int height, int *x, int *y)
{
int bestRow1 = textureHeight;
for (int i = 0; i <= textureWidth - width; i++)
{
int bestRow2 = 0;
int j;
for (j = 0; j < width; j++)
{
if (allocBlocks[i + j] >= bestRow1)
{
break;
}
if (allocBlocks[i + j] > bestRow2)
{
bestRow2 = allocBlocks[i + j];
}
}
// found a free block
if (j == width)
{
*x = i;
*y = bestRow1 = bestRow2;
}
}
if (bestRow1 + height > textureHeight)
{
// no room
return false;
}
// store row offset
for (int i = 0; i < width; i++)
{
allocBlocks[*x + i] = bestRow1 + height;
}
return true;
}

View file

@ -56,15 +56,17 @@ public:
class LightmapTexture class LightmapTexture
{ {
public: public:
LightmapTexture(int width, int height) LightmapTexture(int width, int height);
{
mPixels.resize(width * height * 3); bool MakeRoomForBlock(const int width, const int height, int *x, int *y);
}
uint16_t *Pixels() { return mPixels.data(); } uint16_t *Pixels() { return mPixels.data(); }
private: private:
int textureWidth;
int textureHeight;
std::vector<uint16_t> mPixels; std::vector<uint16_t> mPixels;
std::vector<int> allocBlocks;
}; };
class TraceTask class TraceTask
@ -89,8 +91,6 @@ public:
void AddLightmapLump(FWadWriter &wadFile); void AddLightmapLump(FWadWriter &wadFile);
private: private:
void NewTexture();
bool MakeRoomForBlock(const int width, const int height, int *x, int *y, int *num);
BBox GetBoundsFromSurface(const Surface *surface); BBox GetBoundsFromSurface(const Surface *surface);
Vec3 LightTexelSample(const Vec3 &origin, Surface *surface); Vec3 LightTexelSample(const Vec3 &origin, Surface *surface);
bool EmitFromCeiling(const Surface *surface, const Vec3 &origin, const Vec3 &normal, Vec3 &color); bool EmitFromCeiling(const Surface *surface, const Vec3 &origin, const Vec3 &normal, Vec3 &color);
@ -107,6 +107,8 @@ private:
void CreateSurfaceLights(); void CreateSurfaceLights();
uint16_t *AllocTextureRoom(Surface *surface, int *x, int *y);
FLevel *map; FLevel *map;
int samples = 16; int samples = 16;
int textureWidth = 128; int textureWidth = 128;
@ -116,8 +118,6 @@ private:
std::vector<std::unique_ptr<SurfaceLight>> surfaceLights; std::vector<std::unique_ptr<SurfaceLight>> surfaceLights;
std::vector<std::unique_ptr<LightmapTexture>> textures; std::vector<std::unique_ptr<LightmapTexture>> textures;
std::vector<TraceTask> traceTasks; std::vector<TraceTask> traceTasks;
std::vector<std::vector<int>> allocBlocks;
int numTextures = 0;
int extraSamples = 2; int extraSamples = 2;
int tracedTexels = 0; int tracedTexels = 0;