diff --git a/ClassicalSharp/Blocks/Block.cs b/ClassicalSharp/Blocks/Block.cs index 2607264b0..5ddb1a657 100644 --- a/ClassicalSharp/Blocks/Block.cs +++ b/ClassicalSharp/Blocks/Block.cs @@ -102,8 +102,10 @@ namespace ClassicalSharp { #if USE16_BIT public const BlockID MaxDefinedBlock = 0x3FF; + public const int Shift = 10; #else public const BlockID MaxDefinedBlock = 0xFF; + public const int Shift = 8; #endif public const int Count = MaxDefinedBlock + 1; diff --git a/ClassicalSharp/Blocks/BlockInfo.Culling.cs b/ClassicalSharp/Blocks/BlockInfo.Culling.cs index 7c49d397c..64d6964d8 100644 --- a/ClassicalSharp/Blocks/BlockInfo.Culling.cs +++ b/ClassicalSharp/Blocks/BlockInfo.Culling.cs @@ -18,10 +18,8 @@ namespace ClassicalSharp { public static byte[] CanStretch = new byte[Block.Count]; internal static void UpdateCulling() { - for (int block = 0; block < Block.Count; block++) - CanStretch[block] = 0x3F; - for (int block = 0; block < Block.Count; block++) { + CalcStretch((BlockID)block); for (int neighbour = 0; neighbour < Block.Count; neighbour++) { CalcCulling((BlockID)block, (BlockID)neighbour); } @@ -29,21 +27,36 @@ namespace ClassicalSharp { } internal static void UpdateCulling(BlockID block) { - CanStretch[block] = 0x3F; - + CalcStretch(block); for (int other = 0; other < Block.Count; other++) { CalcCulling(block, (BlockID)other); CalcCulling((BlockID)other, block); } } + static void CalcStretch(BlockID block) { + // faces which can be stretched on X axis + if (MinBB[block].X == 0 && MaxBB[block].X == 1) { + CanStretch[block] |= 0x3C; + } else { + CanStretch[block] &= 0xC3; // ~0x3C + } + + // faces which can be stretched on Z axis + if (MinBB[block].Z == 0 && MaxBB[block].Z == 1) { + CanStretch[block] |= 0x03; + } else { + CanStretch[block] &= 0xFC; // ~0x03 + } + } + static void CalcCulling(BlockID block, BlockID other) { Vector3 bMin = MinBB[block], bMax = MaxBB[block]; Vector3 oMin = MinBB[other], oMax = MaxBB[other]; if (IsLiquid[block]) bMax.Y -= 1.5f/16; if (IsLiquid[other]) oMax.Y -= 1.5f/16; - hidden[block * Block.Count + other] = 0; // set all faces 'not hidden' + hidden[(block << Block.Shift) | other] = 0; // set all faces 'not hidden' if (Draw[block] == DrawType.Sprite) { SetHidden(block, other, Side.Left, true); SetHidden(block, other, Side.Right, true); @@ -52,8 +65,6 @@ namespace ClassicalSharp { SetHidden(block, other, Side.Bottom, oMax.Y == 1); SetHidden(block, other, Side.Top, bMax.Y == 1); } else { - SetXStretch(block, bMin.X == 0 && bMax.X == 1); - SetZStretch(block, bMin.Z == 0 && bMax.Z == 1); bool bothLiquid = IsLiquid[block] && IsLiquid[other]; SetHidden(block, other, Side.Left, oMax.X == 1 && bMin.X == 0); @@ -85,37 +96,20 @@ namespace ClassicalSharp { // e.g. for water / ice, don't need to draw water. byte bType = Collide[block], oType = Collide[other]; - bool canSkip = (bType == CollideType.Solid && oType == CollideType.Solid) - || bType != CollideType.Solid; + bool canSkip = (bType == CollideType.Solid && oType == CollideType.Solid) || bType != CollideType.Solid; return canSkip; } static void SetHidden(BlockID block, BlockID other, int side, bool value) { value = IsHidden(block, other) && FaceOccluded(block, other, side) && value; int bit = value ? 1 : 0; - hidden[block * Block.Count + other] |= (byte)(bit << side); + hidden[(block << Block.Shift) | other] |= (byte)(bit << side); } /// Returns whether the face at the given face of the block /// should be drawn with the neighbour 'other' present on the other side of the face. public static bool IsFaceHidden(BlockID block, BlockID other, int tileSide) { - #if USE16_BIT - return (hidden[(block << 10) | other] & (1 << tileSide)) != 0; - #else - return (hidden[(block << 8) | other] & (1 << tileSide)) != 0; - #endif - } - - static void SetXStretch(BlockID block, bool stretch) { - const byte mask = 0x3C; - CanStretch[block] &= 0xC3; // ~0x3C - CanStretch[block] |= (stretch ? mask : (byte)0); - } - - static void SetZStretch(BlockID block, bool stretch) { - const byte mask = 0x03; - CanStretch[block] &= 0xFC; // ~0x03 - CanStretch[block] |= (stretch ? mask : (byte)0); + return (hidden[(block << Block.Shift) | other] & (1 << tileSide)) != 0; } } } \ No newline at end of file diff --git a/ClassicalSharp/MeshBuilder/Builder.cs b/ClassicalSharp/MeshBuilder/Builder.cs index e89e91484..481fc5fe2 100644 --- a/ClassicalSharp/MeshBuilder/Builder.cs +++ b/ClassicalSharp/MeshBuilder/Builder.cs @@ -202,11 +202,7 @@ namespace ClassicalSharp { X = x; Y = y; Z = z; fullBright = BlockInfo.FullBright[b]; - #if USE16_BIT - int tileIdx = b << 10; - #else - int tileIdx = b << 8; - #endif + int tileIdx = b << Block.Shift; // All of these function calls are inlined as they can be called tens of millions to hundreds of millions of times. if (counts[index] == 0 || diff --git a/src/Client/Block.c b/src/Client/Block.c index 4b0e41e00..895a17789 100644 --- a/src/Client/Block.c +++ b/src/Client/Block.c @@ -345,10 +345,10 @@ void Block_RecalculateBB(BlockID block) { TextureLoc texLoc = Block_GetTexLoc(block, FACE_XMAX); Int32 texX = texLoc & 0x0F, texY = texLoc >> 4; - Real32 topY = Block_GetSpriteBB_TopY(elemSize, texX, texY, bmp); + Real32 topY = Block_GetSpriteBB_TopY(elemSize, texX, texY, bmp); Real32 bottomY = Block_GetSpriteBB_BottomY(elemSize, texX, texY, bmp); - Real32 leftX = Block_GetSpriteBB_LeftX(elemSize, texX, texY, bmp); - Real32 rightX = Block_GetSpriteBB_RightX(elemSize, texX, texY, bmp); + Real32 leftX = Block_GetSpriteBB_LeftX(elemSize, texX, texY, bmp); + Real32 rightX = Block_GetSpriteBB_RightX(elemSize, texX, texY, bmp); Vector3 centre = Vector3_Create3(0.5f, 0, 0.5f); Vector3 minRaw = Vector3_RotateY3(leftX - 0.5f, bottomY, 0, 45.0f * MATH_DEG2RAD); @@ -360,15 +360,20 @@ void Block_RecalculateBB(BlockID block) { } +void Block_CalcStretch(BlockID block) { + /* faces which can be stretched on X axis */ + if (Block_MinBB[block].X == 0.0f && Block_MaxBB[block].X == 1.0f) { + Block_CanStretch[block] |= 0x3C; + } else { + Block_CanStretch[block] &= 0xC3; /* ~0x3C */ + } -void Block_SetXStretch(BlockID block, bool stretch) { - Block_CanStretch[block] &= 0xC3; /* ~0x3C */ - Block_CanStretch[block] |= (stretch ? 0x3C : (UInt8)0); -} - -void Block_SetZStretch(BlockID block, bool stretch) { - Block_CanStretch[block] &= 0xFC; /* ~0x03 */ - Block_CanStretch[block] |= (stretch ? 0x03 : (UInt8)0); + /* faces which can be stretched on Z axis */ + if (Block_MinBB[block].Z == 0.0f && Block_MaxBB[block].Z == 1.0f) { + Block_CanStretch[block] |= 0x03; + } else { + Block_CanStretch[block] &= 0xFC; /* ~0x03 */ + } } void Block_CalcCulling(BlockID block, BlockID other) { @@ -377,7 +382,7 @@ void Block_CalcCulling(BlockID block, BlockID other) { if (Block_IsLiquid[block]) bMax.Y -= 1.5f / 16.0f; if (Block_IsLiquid[other]) oMax.Y -= 1.5f / 16.0f; - Block_Hidden[block * BLOCK_COUNT + other] = 0; /* set all faces 'not hidden' */ + Block_Hidden[(block << BLOCK_SHIFT) | other] = 0; /* set all faces 'not hidden' */ if (Block_Draw[block] == DRAW_SPRITE) { Block_SetHidden(block, other, FACE_XMIN, true); Block_SetHidden(block, other, FACE_XMAX, true); @@ -386,8 +391,6 @@ void Block_CalcCulling(BlockID block, BlockID other) { Block_SetHidden(block, other, FACE_YMIN, oMax.Y == 1.0f); Block_SetHidden(block, other, FACE_YMAX, bMax.Y == 1.0f); } else { - Block_SetXStretch(block, bMin.X == 0 && bMax.X == 1.0f); - Block_SetZStretch(block, bMin.Z == 0 && bMax.Z == 1.0f); bool bothLiquid = Block_IsLiquid[block] && Block_IsLiquid[other]; Block_SetHidden(block, other, FACE_XMIN, oMax.X == 1.0f && bMin.X == 0.0f); @@ -404,10 +407,8 @@ void Block_CalcCulling(BlockID block, BlockID other) { void Block_UpdateCullingAll(void) { Int32 block, neighbour; - for (block = BLOCK_AIR; block < BLOCK_COUNT; block++) - Block_CanStretch[block] = 0x3F; - for (block = BLOCK_AIR; block < BLOCK_COUNT; block++) { + Block_CalcStretch((BlockID)block); for (neighbour = BLOCK_AIR; neighbour < BLOCK_COUNT; neighbour++) { Block_CalcCulling((BlockID)block, (BlockID)neighbour); } @@ -415,8 +416,7 @@ void Block_UpdateCullingAll(void) { } void Block_UpdateCulling(BlockID block) { - Block_CanStretch[block] = 0x3F; - + Block_CalcStretch(block); Int32 other; for (other = BLOCK_AIR; other < BLOCK_COUNT; other++) { Block_CalcCulling(block, (BlockID)other); @@ -442,22 +442,17 @@ bool Block_IsHidden(BlockID block, BlockID other) { /* e.g. for water / ice, don't need to draw water. */ UInt8 bType = Block_Collide[block], oType = Block_Collide[other]; - bool canSkip = (bType == COLLIDE_SOLID && oType == COLLIDE_SOLID) - || bType != COLLIDE_SOLID; + bool canSkip = (bType == COLLIDE_SOLID && oType == COLLIDE_SOLID) || bType != COLLIDE_SOLID; return canSkip; } void Block_SetHidden(BlockID block, BlockID other, Face face, bool value) { value = Block_IsHidden(block, other) && Block_FaceOccluded(block, other, face) && value; - Block_Hidden[block * BLOCK_COUNT + other] |= (UInt8)(value << face); + Block_Hidden[(block << BLOCK_SHIFT) | other] |= (UInt8)(value << face); } bool Block_IsFaceHidden(BlockID block, BlockID other, Face face) { -#if USE16_BIT - return (hidden[(block << 12) | other] & (1 << face)) != 0; -#else - return (Block_Hidden[(block << 8) | other] & (1 << face)) != 0; -#endif + return (Block_Hidden[(block << BLOCK_SHIFT) | other] & (1 << face)) != 0; } diff --git a/src/Client/BlockID.h b/src/Client/BlockID.h index a6ea5b7d3..be33f926f 100644 --- a/src/Client/BlockID.h +++ b/src/Client/BlockID.h @@ -84,9 +84,11 @@ #define BLOCK_CPE_COUNT (BLOCK_MAX_CPE + 1) #if USE16_BIT -#define BLOCK_MAX_DEFINED 0xFFF +#define BLOCK_MAX_DEFINED 0x3FF +#define BLOCK_SHIFT 10 #else #define BLOCK_MAX_DEFINED 0xFF +#define BLOCK_SHIFT 8 #endif #define BLOCK_RAW_NAMES "Air Stone Grass Dirt Cobblestone Wood Sapling Bedrock Water StillWater Lava"\ diff --git a/src/Client/Builder.c b/src/Client/Builder.c index 6a192e87a..f906f3e52 100644 --- a/src/Client/Builder.c +++ b/src/Client/Builder.c @@ -153,11 +153,7 @@ void Builder_Stretch(Int32 x1, Int32 y1, Int32 z1) { Builder_X = x; Builder_Y = y; Builder_Z = z; Builder_FullBright = Block_FullBright[b]; -#if USE16_BIT - Int32 tileIdx = b << 12; -#else - Int32 tileIdx = b << 8; -#endif + Int32 tileIdx = b << BLOCK_SHIFT; /* All of these function calls are inlined as they can be called tens of millions to hundreds of millions of times. */ if (Builder_Counts[index] == 0 ||