summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/LightingThread.cpp92
-rw-r--r--src/LightingThread.h11
2 files changed, 87 insertions, 16 deletions
diff --git a/src/LightingThread.cpp b/src/LightingThread.cpp
index 302473d71..f23f0c5f4 100644
--- a/src/LightingThread.cpp
+++ b/src/LightingThread.cpp
@@ -27,7 +27,8 @@ class cReader :
ROW * OutputRows = (ROW *)m_BlockTypes;
int InputIdx = 0;
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++)
{
@@ -43,6 +44,7 @@ class cReader :
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;
ROW * InputRows = (ROW *)a_Heightmap;
ROW * OutputRows = (ROW *)m_HeightMap;
@@ -53,13 +55,32 @@ class cReader :
OutputRows[OutputIdx] = InputRows[InputIdx++];
OutputIdx += 3;
} // 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:
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
+ 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)
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_BlockTypes(a_BlockTypes),
+ m_HeightMap(a_HeightMap),
+ m_MaxHeight(0)
+ {
+ }
} ;
@@ -225,7 +246,7 @@ void cLightingThread::LightChunk(cLightingChunkStay & a_Item)
// DEBUG: Save chunk data with highlighted seeds for visual inspection:
cFile f4;
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++)
@@ -244,6 +265,7 @@ void cLightingThread::LightChunk(cLightingChunkStay & a_Item)
f4.Write(Seeds, cChunkDef::Width * 3);
}
}
+ f4.Close();
}
//*/
@@ -253,9 +275,9 @@ void cLightingThread::LightChunk(cLightingChunkStay & a_Item)
// DEBUG: Save XY slices of the chunk data and lighting for visual inspection:
cFile f1, f2, f3;
if (
- f1.Open(Printf("Chunk_%d_%d_data.grab", a_Item.x, a_Item.z), cFile::fmWrite) &&
- f2.Open(Printf("Chunk_%d_%d_sky.grab", a_Item.x, a_Item.z), cFile::fmWrite) &&
- f3.Open(Printf("Chunk_%d_%d_glow.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.m_ChunkX, a_Item.m_ChunkZ), 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++)
@@ -274,6 +296,9 @@ void cLightingThread::LightChunk(cLightingChunkStay & a_Item)
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;
- Reader.m_BlockTypes = m_BlockTypes;
- Reader.m_HeightMap = m_HeightMap;
+ cReader Reader(m_BlockTypes, m_HeightMap);
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++)
{
Reader.m_ReadingChunkX = x;
- if (!m_World->GetChunkData(a_ChunkX + x - 1, a_ChunkZ + z - 1, Reader))
- {
- return false;
- }
+ VERIFY(m_World->GetChunkData(a_ChunkX + x - 1, a_ChunkZ + z - 1, Reader));
} // for z
} // for x
memset(m_BlockLight, 0, sizeof(m_BlockLight));
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)
{
int NumSeeds2 = 0;
diff --git a/src/LightingThread.h b/src/LightingThread.h
index 770ae809f..a484fcbed 100644
--- a/src/LightingThread.h
+++ b/src/LightingThread.h
@@ -108,6 +108,9 @@ protected:
cEvent m_evtItemAdded; // Set when queue is appended, or to stop the thread
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
// 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 */
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 */
- bool ReadChunks(int a_ChunkX, int a_ChunkZ);
+ /** Prepares m_BlockTypes and m_HeightMap data; zeroes out the light arrays */
+ void ReadChunks(int a_ChunkX, int a_ChunkZ);
/** Uses m_HeightMap to initialize the m_SkyLight[] data; fills in seeds for the skylight */
void PrepareSkyLight(void);
@@ -145,6 +148,10 @@ protected:
/** Uses m_BlockTypes to initialize the m_BlockLight[] data; fills in seeds for the blocklight */
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 */
void CalcLight(NIBBLETYPE * a_Light);