From a42d1f851748c0cca542d1b0038318d0cbff9fd3 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 6 Apr 2014 23:30:21 +0100 Subject: Blocklight and skylight now compressed --- src/Chunk.cpp | 106 ++++++++++++++++++++++++++++++++++++++++++++------------- src/Chunk.h | 8 ++--- src/ChunkDef.h | 8 ++--- 3 files changed, 90 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 97822048d..7a3e63bd0 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -250,8 +250,14 @@ void cChunk::GetAllData(cChunkDataCallback & a_Callback) a_Callback.BlockMeta (Metas.data()); a_Callback.LightIsValid (m_IsLightValid); - a_Callback.BlockLight (m_BlockLight); - a_Callback.BlockSkyLight(m_BlockSkyLight); + + std::vector BlockLights = m_BlockLight; + BlockLights.resize(NumBlocks / 2); + a_Callback.BlockLight (BlockLights.data()); + + std::vector BlockSkyLights = m_BlockSkyLight; + BlockSkyLights.resize(NumBlocks / 2, 0xff); + a_Callback.BlockSkyLight(BlockSkyLights.data()); for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr) { @@ -285,47 +291,66 @@ void cChunk::SetAllData( memcpy(m_HeightMap, a_HeightMap, sizeof(m_HeightMap)); } - { // Blocktype compression - bool FoundNonAir = false; + { + int IdxWhereNonEmptyStarts = 0; + { // Blocktype compression + bool FoundNonAir = false; + m_BlockTypes.clear(); + + for (int Idx = NumBlocks - 1; Idx >= 0; Idx--) + { + if (a_BlockTypes[Idx] != E_BLOCK_AIR) + { + FoundNonAir = true; + IdxWhereNonEmptyStarts = Idx; + break; + } + } + m_BlockTypes.insert(m_BlockTypes.end(), &a_BlockTypes[0], &a_BlockTypes[IdxWhereNonEmptyStarts + 1]); + } + + { // Blockmeta compression + m_BlockMeta.clear(); + m_BlockMeta.insert(m_BlockMeta.end(), &a_BlockMeta[0], &a_BlockMeta[(IdxWhereNonEmptyStarts + 1) / 2]); + } + } + + if (a_BlockLight != NULL) + { + // Compress blocklight + bool FoundNonEmpty = false; int IdxWhereNonEmptyStarts = 0; - m_BlockTypes.clear(); + m_BlockLight.clear(); - for (int Idx = NumBlocks - 1; Idx >= 0; Idx--) + for (int Idx = (NumBlocks / 2) - 1; Idx >= 0; Idx--) { - if (a_BlockTypes[Idx] != E_BLOCK_AIR) + if (a_BlockLight[Idx] != 0) { - FoundNonAir = true; + FoundNonEmpty = true; IdxWhereNonEmptyStarts = Idx; break; } } - m_BlockTypes.insert(m_BlockTypes.end(), &a_BlockTypes[0], &a_BlockTypes[IdxWhereNonEmptyStarts + 1]); + m_BlockLight.insert(m_BlockLight.end(), &a_BlockLight[0], &a_BlockLight[IdxWhereNonEmptyStarts + 1]); } - { // Blockmeta compression + if (a_BlockSkyLight != NULL) + { + // Compress skylight bool FoundNonEmpty = false; int IdxWhereNonEmptyStarts = 0; - m_BlockMeta.clear(); + m_BlockSkyLight.clear(); for (int Idx = (NumBlocks / 2) - 1; Idx >= 0; Idx--) { - if (a_BlockMeta[Idx] != 0) + if (a_BlockSkyLight[Idx] != 0xff) { FoundNonEmpty = true; IdxWhereNonEmptyStarts = Idx; break; } } - m_BlockMeta.insert(m_BlockMeta.end(), &a_BlockMeta[0], &a_BlockMeta[IdxWhereNonEmptyStarts + 1]); - } - - if (a_BlockLight != NULL) - { - memcpy(m_BlockLight, a_BlockLight, sizeof(m_BlockLight)); - } - if (a_BlockSkyLight != NULL) - { - memcpy(m_BlockSkyLight, a_BlockSkyLight, sizeof(m_BlockSkyLight)); + m_BlockSkyLight.insert(m_BlockSkyLight.end(), &a_BlockSkyLight[0], &a_BlockSkyLight[IdxWhereNonEmptyStarts + 1]); } m_IsLightValid = (a_BlockLight != NULL) && (a_BlockSkyLight != NULL); @@ -371,8 +396,41 @@ void cChunk::SetLight( { // TODO: We might get cases of wrong lighting when a chunk changes in the middle of a lighting calculation. // Postponing until we see how bad it is :) - memcpy(m_BlockLight, a_BlockLight, sizeof(m_BlockLight)); - memcpy(m_BlockSkyLight, a_SkyLight, sizeof(m_BlockSkyLight)); + + { // Compress blocklight + bool FoundNonEmpty = false; + int IdxWhereNonEmptyStarts = 0; + m_BlockLight.clear(); + + for (int Idx = (NumBlocks / 2) - 1; Idx >= 0; Idx--) + { + if (a_BlockLight[Idx] != 0) + { + FoundNonEmpty = true; + IdxWhereNonEmptyStarts = Idx; + break; + } + } + m_BlockLight.insert(m_BlockLight.end(), &a_BlockLight[0], &a_BlockLight[IdxWhereNonEmptyStarts + 1]); + } + + { // Compress skylight + bool FoundNonEmpty = false; + int IdxWhereNonEmptyStarts = 0; + m_BlockSkyLight.clear(); + + for (int Idx = (NumBlocks / 2) - 1; Idx >= 0; Idx--) + { + if (a_SkyLight[Idx] != 0xff) + { + FoundNonEmpty = true; + IdxWhereNonEmptyStarts = Idx; + break; + } + } + m_BlockSkyLight.insert(m_BlockSkyLight.end(), &a_SkyLight[0], &a_SkyLight[IdxWhereNonEmptyStarts + 1]); + } + m_IsLightValid = true; } diff --git a/src/Chunk.h b/src/Chunk.h index d8e4cf6e4..6e2933ff8 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -326,9 +326,9 @@ public: inline void SetMeta(int a_BlockIdx, NIBBLETYPE a_Meta) { cChunkDef::SetNibble(m_BlockMeta, a_BlockIdx, a_Meta); } inline NIBBLETYPE GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockLight, a_RelX, a_RelY, a_RelZ); } - inline NIBBLETYPE GetSkyLight (int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockSkyLight, a_RelX, a_RelY, a_RelZ); } + inline NIBBLETYPE GetSkyLight (int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockSkyLight, a_RelX, a_RelY, a_RelZ, true); } inline NIBBLETYPE GetBlockLight(int a_Idx) const {return cChunkDef::GetNibble(m_BlockLight, a_Idx); } - inline NIBBLETYPE GetSkyLight (int a_Idx) const {return cChunkDef::GetNibble(m_BlockSkyLight, a_Idx); } + inline NIBBLETYPE GetSkyLight (int a_Idx) const {return cChunkDef::GetNibble(m_BlockSkyLight, a_Idx, true); } /** Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */ bool UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const; @@ -423,8 +423,8 @@ private: // TODO: Make these pointers and don't allocate what isn't needed std::vector m_BlockTypes; std::vector m_BlockMeta; - NIBBLETYPE m_BlockLight [cChunkDef::NumBlocks / 2]; - NIBBLETYPE m_BlockSkyLight[cChunkDef::NumBlocks / 2]; + std::vector m_BlockLight; + std::vector m_BlockSkyLight; cChunkDef::HeightMap m_HeightMap; cChunkDef::BiomeMap m_BiomeMap; diff --git a/src/ChunkDef.h b/src/ChunkDef.h index 3793bd95a..d744d24b2 100644 --- a/src/ChunkDef.h +++ b/src/ChunkDef.h @@ -232,13 +232,13 @@ public: } - static NIBBLETYPE GetNibble(const std::vector & a_Buffer, int a_BlockIdx) + static NIBBLETYPE GetNibble(const std::vector & a_Buffer, int a_BlockIdx, bool a_IsSkyLightNibble = false) { if ((a_BlockIdx > -1) && (a_BlockIdx < NumBlocks)) { if (a_Buffer.empty() || (a_BlockIdx / 2 > a_Buffer.size() - 1)) { - return 0; + return (a_IsSkyLightNibble ? 0xff : 0); } return (a_Buffer[a_BlockIdx / 2] >> ((a_BlockIdx & 1) * 4)) & 0x0f; } @@ -259,14 +259,14 @@ public: } - static NIBBLETYPE GetNibble(const std::vector & a_Buffer, int x, int y, int z) + static NIBBLETYPE GetNibble(const std::vector & a_Buffer, int x, int y, int z, bool a_IsSkyLightNibble = false) { if ((x < Width) && (x > -1) && (y < Height) && (y > -1) && (z < Width) && (z > -1)) { int Index = MakeIndexNoCheck(x, y, z); if (a_Buffer.empty() || (Index / 2 > a_Buffer.size() - 1)) { - return 0; + return (a_IsSkyLightNibble ? 0xff : 0); } return (a_Buffer[Index / 2] >> ((Index & 1) * 4)) & 0x0f; } -- cgit v1.2.3