From 3201d1bf169ca99e4cdbfad7601f6aed89b3c76c Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 4 Apr 2014 23:16:52 +0100 Subject: Nibbletypes are compressed + Added nibble compression * Fixed an off by one --- src/Chunk.cpp | 49 +++++++++++++++++++++++++------------ src/Chunk.h | 2 +- src/ChunkDef.h | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 110 insertions(+), 18 deletions(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index c2caafe45..97822048d 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -243,9 +243,12 @@ void cChunk::GetAllData(cChunkDataCallback & a_Callback) std::vector Blocks = m_BlockTypes; Blocks.resize(NumBlocks); - a_Callback.BlockTypes (Blocks.data()); - a_Callback.BlockMeta (m_BlockMeta); + + std::vector Metas = m_BlockMeta; + Metas.resize(NumBlocks / 2); + a_Callback.BlockMeta (Metas.data()); + a_Callback.LightIsValid (m_IsLightValid); a_Callback.BlockLight (m_BlockLight); a_Callback.BlockSkyLight(m_BlockSkyLight); @@ -282,23 +285,40 @@ void cChunk::SetAllData( memcpy(m_HeightMap, a_HeightMap, sizeof(m_HeightMap)); } - bool FoundNonAir = false; - int IdxWhereNonEmptyStarts = 0; - m_BlockTypes.clear(); + { // Blocktype compression + bool FoundNonAir = false; + int IdxWhereNonEmptyStarts = 0; + m_BlockTypes.clear(); - for (int Idx = NumBlocks - 1; Idx >= 0; Idx--) - { - if (a_BlockTypes[Idx] != E_BLOCK_AIR) + for (int Idx = NumBlocks - 1; Idx >= 0; Idx--) { - FoundNonAir = true; - IdxWhereNonEmptyStarts = Idx; - break; + 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]); } - m_BlockTypes.insert(m_BlockTypes.end(), &a_BlockTypes[0], &a_BlockTypes[IdxWhereNonEmptyStarts + 1]); + { // Blockmeta compression + bool FoundNonEmpty = false; + int IdxWhereNonEmptyStarts = 0; + m_BlockMeta.clear(); + + for (int Idx = (NumBlocks / 2) - 1; Idx >= 0; Idx--) + { + if (a_BlockMeta[Idx] != 0) + { + FoundNonEmpty = true; + IdxWhereNonEmptyStarts = Idx; + break; + } + } + m_BlockMeta.insert(m_BlockMeta.end(), &a_BlockMeta[0], &a_BlockMeta[IdxWhereNonEmptyStarts + 1]); + } - memcpy(m_BlockMeta, a_BlockMeta, sizeof(m_BlockMeta)); if (a_BlockLight != NULL) { memcpy(m_BlockLight, a_BlockLight, sizeof(m_BlockLight)); @@ -1548,9 +1568,8 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT if (m_BlockTypes.empty() || (index > m_BlockTypes.size() - 1) /* Vector starts from zero, .size() starts from 1 */) { - m_BlockTypes.resize(index); + m_BlockTypes.resize(index + 1); } - m_BlockTypes[index] = a_BlockType; // The client doesn't need to distinguish between stationary and nonstationary fluids: diff --git a/src/Chunk.h b/src/Chunk.h index ef6a11006..d8e4cf6e4 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -422,7 +422,7 @@ private: // TODO: Make these pointers and don't allocate what isn't needed std::vector m_BlockTypes; - NIBBLETYPE m_BlockMeta [cChunkDef::NumBlocks / 2]; + std::vector m_BlockMeta; NIBBLETYPE m_BlockLight [cChunkDef::NumBlocks / 2]; NIBBLETYPE m_BlockSkyLight[cChunkDef::NumBlocks / 2]; diff --git a/src/ChunkDef.h b/src/ChunkDef.h index 9c7753820..3793bd95a 100644 --- a/src/ChunkDef.h +++ b/src/ChunkDef.h @@ -230,6 +230,21 @@ public: ASSERT(!"cChunkDef::GetNibble(): index out of chunk range!"); return 0; } + + + static NIBBLETYPE GetNibble(const std::vector & a_Buffer, int a_BlockIdx) + { + if ((a_BlockIdx > -1) && (a_BlockIdx < NumBlocks)) + { + if (a_Buffer.empty() || (a_BlockIdx / 2 > a_Buffer.size() - 1)) + { + return 0; + } + return (a_Buffer[a_BlockIdx / 2] >> ((a_BlockIdx & 1) * 4)) & 0x0f; + } + ASSERT(!"cChunkDef::GetNibble(): index out of chunk range!"); + return 0; + } static NIBBLETYPE GetNibble(const NIBBLETYPE * a_Buffer, int x, int y, int z) @@ -244,6 +259,22 @@ public: } + static NIBBLETYPE GetNibble(const std::vector & a_Buffer, int x, int y, int z) + { + 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_Buffer[Index / 2] >> ((Index & 1) * 4)) & 0x0f; + } + ASSERT(!"cChunkDef::GetNibble(): coords out of chunk range!"); + return 0; + } + + static void SetNibble(NIBBLETYPE * a_Buffer, int a_BlockIdx, NIBBLETYPE a_Nibble) { if ((a_BlockIdx < 0) || (a_BlockIdx >= NumBlocks)) @@ -256,6 +287,24 @@ public: ((a_Nibble & 0x0f) << ((a_BlockIdx & 1) * 4)) // The nibble being set ); } + + + static void SetNibble(std::vector & a_Buffer, int a_BlockIdx, NIBBLETYPE a_Nibble) + { + if ((a_BlockIdx < 0) || (a_BlockIdx >= NumBlocks)) + { + ASSERT(!"cChunkDef::SetNibble(): index out of range!"); + return; + } + if (a_Buffer.empty() || (a_BlockIdx / 2 > a_Buffer.size() - 1)) + { + a_Buffer.resize((a_BlockIdx / 2) + 1); + } + a_Buffer[a_BlockIdx / 2] = static_cast( + (a_Buffer[a_BlockIdx / 2] & (0xf0 >> ((a_BlockIdx & 1) * 4))) | // The untouched nibble + ((a_Nibble & 0x0f) << ((a_BlockIdx & 1) * 4)) // The nibble being set + ); + } static void SetNibble(NIBBLETYPE * a_Buffer, int x, int y, int z, NIBBLETYPE a_Nibble) @@ -278,13 +327,37 @@ public: } - inline static NIBBLETYPE GetNibble(const NIBBLETYPE * a_Buffer, const Vector3i & a_BlockPos ) + static void SetNibble(std::vector & a_Buffer, int x, int y, int z, NIBBLETYPE a_Nibble) + { + if ( + (x >= Width) || (x < 0) || + (y >= Height) || (y < 0) || + (z >= Width) || (z < 0) + ) + { + ASSERT(!"cChunkDef::SetNibble(): index out of range!"); + return; + } + + int Index = MakeIndexNoCheck(x, y, z); + if (a_Buffer.empty() || (Index / 2 > a_Buffer.size() - 1)) + { + a_Buffer.resize((Index / 2) + 1); + } + a_Buffer[Index / 2] = static_cast( + (a_Buffer[Index / 2] & (0xf0 >> ((Index & 1) * 4))) | // The untouched nibble + ((a_Nibble & 0x0f) << ((Index & 1) * 4)) // The nibble being set + ); + } + + + inline static NIBBLETYPE GetNibble(const NIBBLETYPE * a_Buffer, const Vector3i & a_BlockPos) { return GetNibble(a_Buffer, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z ); } - inline static void SetNibble(NIBBLETYPE * a_Buffer, const Vector3i & a_BlockPos, NIBBLETYPE a_Value ) + inline static void SetNibble(NIBBLETYPE * a_Buffer, const Vector3i & a_BlockPos, NIBBLETYPE a_Value) { SetNibble( a_Buffer, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_Value ); } -- cgit v1.2.3