Merge pull request #883 from mc-server/CutOffLighting
Lighting reads blocktypes only for blocks under heightmap.
This commit is contained in:
commit
4fddbf9dfc
9
src/ChunkDef.cpp
Normal file
9
src/ChunkDef.cpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
#include "ChunkDef.h"
|
||||||
|
|
||||||
|
// It appears that failing to have this definition causes link errors as cChunkDef::Height is not
|
||||||
|
// defined. It also appears that we can have the initalizer in the declaration so it can be inlined
|
||||||
|
// if the declaration is in a class????
|
||||||
|
const int cChunkDef::Height;
|
@ -23,7 +23,8 @@ class cReader :
|
|||||||
BLOCKTYPE * OutputRows = m_BlockTypes;
|
BLOCKTYPE * OutputRows = m_BlockTypes;
|
||||||
int InputIdx = 0;
|
int InputIdx = 0;
|
||||||
int OutputIdx = m_ReadingChunkX + m_ReadingChunkZ * cChunkDef::Width * 3;
|
int OutputIdx = m_ReadingChunkX + m_ReadingChunkZ * cChunkDef::Width * 3;
|
||||||
for (int y = 0; y < cChunkDef::Height; y++)
|
int MaxHeight = std::min(cChunkDef::Height, m_MaxHeight + 16); // Need 16 blocks above the highest
|
||||||
|
for (int y = 0; y < MaxHeight; y++)
|
||||||
{
|
{
|
||||||
for (int z = 0; z < cChunkDef::Width; z++)
|
for (int z = 0; z < cChunkDef::Width; z++)
|
||||||
{
|
{
|
||||||
@ -40,6 +41,7 @@ class cReader :
|
|||||||
|
|
||||||
virtual void HeightMap(const cChunkDef::HeightMap * a_Heightmap) override
|
virtual void HeightMap(const cChunkDef::HeightMap * a_Heightmap) override
|
||||||
{
|
{
|
||||||
|
// Copy the entire heightmap, distribute it into the 3x3 chunk blob:
|
||||||
typedef struct {HEIGHTTYPE m_Row[16]; } ROW;
|
typedef struct {HEIGHTTYPE m_Row[16]; } ROW;
|
||||||
ROW * InputRows = (ROW *)a_Heightmap;
|
ROW * InputRows = (ROW *)a_Heightmap;
|
||||||
ROW * OutputRows = (ROW *)m_HeightMap;
|
ROW * OutputRows = (ROW *)m_HeightMap;
|
||||||
@ -50,13 +52,32 @@ class cReader :
|
|||||||
OutputRows[OutputIdx] = InputRows[InputIdx++];
|
OutputRows[OutputIdx] = InputRows[InputIdx++];
|
||||||
OutputIdx += 3;
|
OutputIdx += 3;
|
||||||
} // for z
|
} // for z
|
||||||
|
|
||||||
|
// Find the highest block in the entire chunk, use it as a base for m_MaxHeight:
|
||||||
|
HEIGHTTYPE MaxHeight = m_MaxHeight;
|
||||||
|
for (size_t i = 0; i < ARRAYCOUNT(*a_Heightmap); i++)
|
||||||
|
{
|
||||||
|
if ((*a_Heightmap)[i] > MaxHeight)
|
||||||
|
{
|
||||||
|
MaxHeight = (*a_Heightmap)[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_MaxHeight = MaxHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int m_ReadingChunkX; // 0, 1 or 2; x-offset of the chunk we're reading from the BlockTypes start
|
int m_ReadingChunkX; // 0, 1 or 2; x-offset of the chunk we're reading from the BlockTypes start
|
||||||
int m_ReadingChunkZ; // 0, 1 or 2; z-offset of the chunk we're reading from the BlockTypes start
|
int m_ReadingChunkZ; // 0, 1 or 2; z-offset of the chunk we're reading from the BlockTypes start
|
||||||
|
HEIGHTTYPE m_MaxHeight; // Maximum value in this chunk's heightmap
|
||||||
BLOCKTYPE * m_BlockTypes; // 3x3 chunks of block types, organized as a single XZY blob of data (instead of 3x3 XZY blobs)
|
BLOCKTYPE * m_BlockTypes; // 3x3 chunks of block types, organized as a single XZY blob of data (instead of 3x3 XZY blobs)
|
||||||
HEIGHTTYPE * m_HeightMap; // 3x3 chunks of height map, organized as a single XZY blob of data (instead of 3x3 XZY blobs)
|
HEIGHTTYPE * m_HeightMap; // 3x3 chunks of height map, organized as a single XZY blob of data (instead of 3x3 XZY blobs)
|
||||||
|
|
||||||
|
cReader(BLOCKTYPE * a_BlockTypes, HEIGHTTYPE * a_HeightMap) :
|
||||||
|
m_MaxHeight(0),
|
||||||
|
m_BlockTypes(a_BlockTypes),
|
||||||
|
m_HeightMap(a_HeightMap)
|
||||||
|
{
|
||||||
|
}
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
@ -224,7 +245,7 @@ void cLightingThread::LightChunk(cLightingChunkStay & a_Item)
|
|||||||
// DEBUG: Save chunk data with highlighted seeds for visual inspection:
|
// DEBUG: Save chunk data with highlighted seeds for visual inspection:
|
||||||
cFile f4;
|
cFile f4;
|
||||||
if (
|
if (
|
||||||
f4.Open(Printf("Chunk_%d_%d_seeds.grab", a_Item.x, a_Item.z), cFile::fmWrite)
|
f4.Open(Printf("Chunk_%d_%d_seeds.grab", a_Item.m_ChunkX, a_Item.m_ChunkZ), cFile::fmWrite)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
for (int z = 0; z < cChunkDef::Width * 3; z++)
|
for (int z = 0; z < cChunkDef::Width * 3; z++)
|
||||||
@ -243,6 +264,7 @@ void cLightingThread::LightChunk(cLightingChunkStay & a_Item)
|
|||||||
f4.Write(Seeds, cChunkDef::Width * 3);
|
f4.Write(Seeds, cChunkDef::Width * 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
f4.Close();
|
||||||
}
|
}
|
||||||
//*/
|
//*/
|
||||||
|
|
||||||
@ -252,9 +274,9 @@ void cLightingThread::LightChunk(cLightingChunkStay & a_Item)
|
|||||||
// DEBUG: Save XY slices of the chunk data and lighting for visual inspection:
|
// DEBUG: Save XY slices of the chunk data and lighting for visual inspection:
|
||||||
cFile f1, f2, f3;
|
cFile f1, f2, f3;
|
||||||
if (
|
if (
|
||||||
f1.Open(Printf("Chunk_%d_%d_data.grab", a_Item.x, a_Item.z), cFile::fmWrite) &&
|
f1.Open(Printf("Chunk_%d_%d_data.grab", a_Item.m_ChunkX, a_Item.m_ChunkZ), cFile::fmWrite) &&
|
||||||
f2.Open(Printf("Chunk_%d_%d_sky.grab", a_Item.x, a_Item.z), cFile::fmWrite) &&
|
f2.Open(Printf("Chunk_%d_%d_sky.grab", a_Item.m_ChunkX, a_Item.m_ChunkZ), cFile::fmWrite) &&
|
||||||
f3.Open(Printf("Chunk_%d_%d_glow.grab", a_Item.x, a_Item.z), cFile::fmWrite)
|
f3.Open(Printf("Chunk_%d_%d_glow.grab", a_Item.m_ChunkX, a_Item.m_ChunkZ), cFile::fmWrite)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
for (int z = 0; z < cChunkDef::Width * 3; z++)
|
for (int z = 0; z < cChunkDef::Width * 3; z++)
|
||||||
@ -273,6 +295,9 @@ void cLightingThread::LightChunk(cLightingChunkStay & a_Item)
|
|||||||
f3.Write(BlockLight, cChunkDef::Width * 3);
|
f3.Write(BlockLight, cChunkDef::Width * 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
f1.Close();
|
||||||
|
f2.Close();
|
||||||
|
f3.Close();
|
||||||
}
|
}
|
||||||
//*/
|
//*/
|
||||||
|
|
||||||
@ -293,11 +318,9 @@ void cLightingThread::LightChunk(cLightingChunkStay & a_Item)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cLightingThread::ReadChunks(int a_ChunkX, int a_ChunkZ)
|
void cLightingThread::ReadChunks(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
cReader Reader;
|
cReader Reader(m_BlockTypes, m_HeightMap);
|
||||||
Reader.m_BlockTypes = m_BlockTypes;
|
|
||||||
Reader.m_HeightMap = m_HeightMap;
|
|
||||||
|
|
||||||
for (int z = 0; z < 3; z++)
|
for (int z = 0; z < 3; z++)
|
||||||
{
|
{
|
||||||
@ -305,16 +328,13 @@ bool cLightingThread::ReadChunks(int a_ChunkX, int a_ChunkZ)
|
|||||||
for (int x = 0; x < 3; x++)
|
for (int x = 0; x < 3; x++)
|
||||||
{
|
{
|
||||||
Reader.m_ReadingChunkX = x;
|
Reader.m_ReadingChunkX = x;
|
||||||
if (!m_World->GetChunkData(a_ChunkX + x - 1, a_ChunkZ + z - 1, Reader))
|
VERIFY(m_World->GetChunkData(a_ChunkX + x - 1, a_ChunkZ + z - 1, Reader));
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} // for z
|
} // for z
|
||||||
} // for x
|
} // for x
|
||||||
|
|
||||||
memset(m_BlockLight, 0, sizeof(m_BlockLight));
|
memset(m_BlockLight, 0, sizeof(m_BlockLight));
|
||||||
memset(m_SkyLight, 0, sizeof(m_SkyLight));
|
memset(m_SkyLight, 0, sizeof(m_SkyLight));
|
||||||
return true;
|
m_MaxHeight = Reader.m_MaxHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -405,6 +425,50 @@ void cLightingThread::PrepareBlockLight(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cLightingThread::PrepareBlockLight2(void)
|
||||||
|
{
|
||||||
|
// Clear seeds:
|
||||||
|
memset(m_IsSeed1, 0, sizeof(m_IsSeed1));
|
||||||
|
memset(m_IsSeed2, 0, sizeof(m_IsSeed2));
|
||||||
|
m_NumSeeds = 0;
|
||||||
|
|
||||||
|
// Add each emissive block into the seeds:
|
||||||
|
for (int y = 0; y < m_MaxHeight; y++)
|
||||||
|
{
|
||||||
|
int BaseY = y * BlocksPerYLayer; // Partial offset into m_BlockTypes for the Y coord
|
||||||
|
for (int z = 1; z < cChunkDef::Width * 3 - 1; z++)
|
||||||
|
{
|
||||||
|
int HBaseZ = z * cChunkDef::Width * 3; // Partial offset into m_Heightmap for the Z coord
|
||||||
|
int BaseZ = BaseY + HBaseZ; // Partial offset into m_BlockTypes for the Y and Z coords
|
||||||
|
for (int x = 1; x < cChunkDef::Width * 3 - 1; x++)
|
||||||
|
{
|
||||||
|
int idx = BaseZ + x;
|
||||||
|
if (y > m_HeightMap[HBaseZ + x])
|
||||||
|
{
|
||||||
|
// We're above the heightmap, ignore the block
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cBlockInfo::GetLightValue(m_BlockTypes[idx]) == 0)
|
||||||
|
{
|
||||||
|
// Not a light-emissive block
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add current block as a seed:
|
||||||
|
m_IsSeed1[idx] = true;
|
||||||
|
m_SeedIdx1[m_NumSeeds++] = idx;
|
||||||
|
|
||||||
|
// Light it up:
|
||||||
|
m_BlockLight[idx] = cBlockInfo::GetLightValue(m_BlockTypes[idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cLightingThread::CalcLight(NIBBLETYPE * a_Light)
|
void cLightingThread::CalcLight(NIBBLETYPE * a_Light)
|
||||||
{
|
{
|
||||||
int NumSeeds2 = 0;
|
int NumSeeds2 = 0;
|
||||||
|
@ -108,6 +108,9 @@ protected:
|
|||||||
cEvent m_evtItemAdded; // Set when queue is appended, or to stop the thread
|
cEvent m_evtItemAdded; // Set when queue is appended, or to stop the thread
|
||||||
cEvent m_evtQueueEmpty; // Set when the queue gets empty
|
cEvent m_evtQueueEmpty; // Set when the queue gets empty
|
||||||
|
|
||||||
|
/** The highest block in the current 3x3 chunk data */
|
||||||
|
HEIGHTTYPE m_MaxHeight;
|
||||||
|
|
||||||
|
|
||||||
// Buffers for the 3x3 chunk data
|
// Buffers for the 3x3 chunk data
|
||||||
// These buffers alone are 1.7 MiB in size, therefore they cannot be located on the stack safely - some architectures may have only 1 MiB for stack, or even less
|
// These buffers alone are 1.7 MiB in size, therefore they cannot be located on the stack safely - some architectures may have only 1 MiB for stack, or even less
|
||||||
@ -136,8 +139,8 @@ protected:
|
|||||||
/** Lights the entire chunk. If neighbor chunks don't exist, touches them and re-queues the chunk */
|
/** Lights the entire chunk. If neighbor chunks don't exist, touches them and re-queues the chunk */
|
||||||
void LightChunk(cLightingChunkStay & a_Item);
|
void LightChunk(cLightingChunkStay & a_Item);
|
||||||
|
|
||||||
/** Prepares m_BlockTypes and m_HeightMap data; returns false if any of the chunks fail. Zeroes out the light arrays */
|
/** Prepares m_BlockTypes and m_HeightMap data; zeroes out the light arrays */
|
||||||
bool ReadChunks(int a_ChunkX, int a_ChunkZ);
|
void ReadChunks(int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
/** Uses m_HeightMap to initialize the m_SkyLight[] data; fills in seeds for the skylight */
|
/** Uses m_HeightMap to initialize the m_SkyLight[] data; fills in seeds for the skylight */
|
||||||
void PrepareSkyLight(void);
|
void PrepareSkyLight(void);
|
||||||
@ -145,6 +148,10 @@ protected:
|
|||||||
/** Uses m_BlockTypes to initialize the m_BlockLight[] data; fills in seeds for the blocklight */
|
/** Uses m_BlockTypes to initialize the m_BlockLight[] data; fills in seeds for the blocklight */
|
||||||
void PrepareBlockLight(void);
|
void PrepareBlockLight(void);
|
||||||
|
|
||||||
|
/** Same as PrepareBlockLight(), but uses a different traversal scheme; possibly better perf cache-wise.
|
||||||
|
To be compared in perf benchmarks. */
|
||||||
|
void PrepareBlockLight2(void);
|
||||||
|
|
||||||
/** Calculates light in the light array specified, using stored seeds */
|
/** Calculates light in the light array specified, using stored seeds */
|
||||||
void CalcLight(NIBBLETYPE * a_Light);
|
void CalcLight(NIBBLETYPE * a_Light);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user