Lighting: Fixed underwater lighting (FS #369)

git-svn-id: http://mc-server.googlecode.com/svn/trunk@1444 0a769ca7-a7f5-676a-18bf-c427514a06d6
master
madmaxoft@gmail.com 2013-05-05 14:48:18 +00:00
parent d303a60e11
commit 1e350218cc
3 changed files with 82 additions and 50 deletions

View File

@ -385,10 +385,10 @@ public:
g_BlockSpreadLightFalloff[E_BLOCK_WOODEN_DOOR] = 1;
// Light in water and lava dissapears faster:
g_BlockSpreadLightFalloff[E_BLOCK_LAVA] = 2;
g_BlockSpreadLightFalloff[E_BLOCK_STATIONARY_LAVA] = 2;
g_BlockSpreadLightFalloff[E_BLOCK_STATIONARY_WATER] = 2;
g_BlockSpreadLightFalloff[E_BLOCK_WATER] = 2;
g_BlockSpreadLightFalloff[E_BLOCK_LAVA] = 3;
g_BlockSpreadLightFalloff[E_BLOCK_STATIONARY_LAVA] = 3;
g_BlockSpreadLightFalloff[E_BLOCK_STATIONARY_WATER] = 3;
g_BlockSpreadLightFalloff[E_BLOCK_WATER] = 3;
// Transparent blocks
g_BlockTransparent[E_BLOCK_AIR] = true;

View File

@ -279,40 +279,66 @@ void cLightingThread::LightChunk(cLightingThread::sItem & a_Item)
CalcLight(m_BlockLight);
PrepareSkyLight();
/*
// 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)
)
{
for (int z = 0; z < cChunkDef::Width * 3; z++)
{
for (int y = cChunkDef::Height / 2; y >= 0; y--)
{
unsigned char Seeds [cChunkDef::Width * 3];
memcpy(Seeds, m_BlockTypes + y * BlocksPerYLayer + z * cChunkDef::Width * 3, cChunkDef::Width * 3);
for (int x = 0; x < cChunkDef::Width * 3; x++)
{
if (m_IsSeed1[y * BlocksPerYLayer + z * cChunkDef::Width * 3 + x])
{
Seeds[x] = E_BLOCK_DIAMOND_BLOCK;
}
}
f4.Write(Seeds, cChunkDef::Width * 3);
}
}
}
//*/
CalcLight(m_SkyLight);
/*
// 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)
)
{
for (int z = 0; z < cChunkDef::Width * 3; z++)
{
for (int y = cChunkDef::Height / 2; y >= 0; y--)
{
f1.Write(m_BlockTypes + y * BlocksPerYLayer + z * cChunkDef::Width * 3, cChunkDef::Width * 3);
unsigned char SkyLight [cChunkDef::Width * 3];
unsigned char BlockLight[cChunkDef::Width * 3];
for (int x = 0; x < cChunkDef::Width * 3; x++)
{
SkyLight[x] = m_SkyLight [y * BlocksPerYLayer + z * cChunkDef::Width * 3 + x] << 4;
BlockLight[x] = m_BlockLight[y * BlocksPerYLayer + z * cChunkDef::Width * 3 + x] << 4;
}
f2.Write(SkyLight, cChunkDef::Width * 3);
f3.Write(BlockLight, cChunkDef::Width * 3);
}
}
}
//*/
CompressLight(m_BlockLight, BlockLight);
CompressLight(m_SkyLight, SkyLight);
/*
// DEBUG:
{
cFile f("chunk_BlockTypes.dat", cFile::fmWrite);
if (f.IsOpen())
{
f.Write(m_BlockTypes, sizeof(m_BlockTypes));
}
}
// DEBUG:
{
cFile f("Chunk_SkyLight.dat", cFile::fmWrite);
if (f.IsOpen())
{
f.Write(m_SkyLight, sizeof(m_SkyLight));
}
}
// DEBUG:
{
cFile f("Chunk_BlockLight.dat", cFile::fmWrite);
if (f.IsOpen())
{
f.Write(m_BlockLight, sizeof(m_BlockLight));
}
}
*/
m_World->ChunkLighted(a_Item.x, a_Item.z, BlockLight, SkyLight);
if (a_Item.m_Callback != NULL)
@ -374,25 +400,22 @@ void cLightingThread::PrepareSkyLight(void)
int Neighbor4 = m_HeightMap[idx - cChunkDef::Width * 3] + 1; // Z - 1
int MaxNeighbor = MAX(MAX(Neighbor1, Neighbor2), MAX(Neighbor3, Neighbor4)); // Maximum of the four neighbors
// TODO: The following cycle can be transofrmed into two separate cycles with no condition inside them, one lighting and the other seeding
for (int y = Current, Index = idx + y * BlocksPerYLayer; y < cChunkDef::Height; y++, Index += BlocksPerYLayer)
// Fill the column from the top down to Current with all-light:
for (int y = cChunkDef::Height - 1, Index = idx + y * BlocksPerYLayer; y >= Current; y--, Index -= BlocksPerYLayer)
{
m_SkyLight[Index] = 15;
}
// Add Current as a seed:
int CurrentIdx = idx + Current * BlocksPerYLayer;
m_IsSeed1[CurrentIdx] = true;
m_SeedIdx1[m_NumSeeds++] = CurrentIdx;
// Add seed from Current up to the highest neighbor:
for (int y = Current + 1, Index = idx + y * BlocksPerYLayer; y < MaxNeighbor; y++, Index += BlocksPerYLayer)
{
// If all the XZ neighbors are lower than y, abort for the current column (but light up the rest of it):
if (y >= MaxNeighbor)
{
for (int y2 = y; y2 < cChunkDef::Height; y2++, Index += BlocksPerYLayer)
{
m_SkyLight[Index] = 15;
} // for y2
break; // for y
}
// Add current block as a seed:
m_IsSeed1[Index] = true;
m_SeedIdx1[m_NumSeeds++] = Index;
// Light it up to full skylight:
m_SkyLight[Index] = 15;
}
}
}

View File

@ -29,6 +29,11 @@
/** If defined, the BlockSkyLight values will be copied over to BlockLight upon chunk saving,
thus making skylight visible in Minutor's Lighting mode
*/
// #define DEBUG_SKYLIGHT
/** Maximum number of MCA files that are cached in memory.
Since only the header is actually in the memory, this number can be high, but still, each file means an OS FS handle.
*/
@ -416,7 +421,11 @@ bool cWSSAnvil::SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_
int SliceSizeNibble = SliceSizeBlock / 2;
const char * BlockTypes = (const char *)(Serializer.m_BlockTypes);
const char * BlockMetas = (const char *)(Serializer.m_BlockMetas);
const char * BlockLight = (const char *)(Serializer.m_BlockLight);
#ifdef DEBUG_SKYLIGHT
const char * BlockLight = (const char *)(Serializer.m_BlockSkyLight);
#else
const char * BlockLight = (const char *)(Serializer.m_BlockLight);
#endif
const char * BlockSkyLight = (const char *)(Serializer.m_BlockSkyLight);
for (int Y = 0; Y < 16; Y++)
{