/******************************************************************** Minecraft: Pocket Edition - Decompilation Project Copyright (C) 2023 iProgramInCpp The following code is licensed under the BSD 1 clause license. SPDX-License-Identifier: BSD-1-Clause ********************************************************************/ #include "TileRenderer.hpp" #include "client/app/Minecraft.hpp" #include "client/renderer/PatchManager.hpp" #include "world/tile/FireTile.hpp" #include "world/tile/LiquidTile.hpp" #include "client/renderer/GrassColor.hpp" #include "client/renderer/FoliageColor.hpp" bool TileRenderer::m_bFancyGrass = false; bool TileRenderer::m_bBiomeColors = false; void TileRenderer::_init() { m_textureOverride = -1; field_8 = false; m_bDisableCulling = false; m_bAmbientOcclusion = false; field_C = 0; field_10 = 0; field_14 = 0; field_18 = 0; field_1C = 0; field_20 = 0; field_24 = 0; field_28 = 0; field_2C = 0; field_30 = 0; field_34 = 0; field_38 = 0; field_3C = 0; field_40 = 0; field_44 = 0; field_48 = 0; field_4C = 0; field_50 = 0; field_54 = 0; field_58 = 0; field_5C = 0; field_60 = 0; field_64 = 0; field_68 = 0; field_6C = 0; field_70 = 0; field_74 = 0; field_78 = 1; field_AC = false; field_AD = false; field_AE = false; field_AF = false; field_B0 = false; field_B1 = false; field_B2 = false; field_B3 = false; field_B4 = false; field_B5 = false; field_B6 = false; field_B7 = false; } TileRenderer::TileRenderer() { _init(); #ifndef ORIGINAL_CODE // @BUG: Not initializing level source m_pLevelSource = nullptr; #endif } TileRenderer::TileRenderer(LevelSource* pLevelSource) { _init(); m_pLevelSource = pLevelSource; } float TileRenderer::getWaterHeight(int x, int y, int z, const Material* pCheckMtl) { int iBias = 0; float fHeight = 0.0f; for (int i = 0; i < 4; i++) { int checkX = x - (i & 1); int checkY = y; int checkZ = z - ((i >> 1) & 1); if (m_pLevelSource->getMaterial(checkX, checkY + 1, checkZ) == pCheckMtl) return 1.0f; Material* pMtl = m_pLevelSource->getMaterial(checkX, checkY, checkZ); if (pMtl == pCheckMtl) { int data = m_pLevelSource->getData(checkX, checkY, checkZ); if (data >= 8 || data == 0) { fHeight += LiquidTile::getWaterVolume(data) * 10.0f; iBias += 10; } fHeight += LiquidTile::getWaterVolume(data); iBias++; continue; } if (!pMtl->isSolid()) { fHeight++; iBias++; } } return 1.0f - fHeight / float(iBias); } bool TileRenderer::canRender(int renderShape) { return renderShape == SHAPE_SOLID || renderShape == SHAPE_STAIRS; } // @NOTE: This sucks! Very badly! But it's how they did it. void TileRenderer::renderEast(Tile* tile, float x, float y, float z, int texture) { static constexpr float C_RATIO = 1.0f / 256.0f; if (m_textureOverride >= 0) texture = m_textureOverride; float texX = float(16 * (texture % 16)); float texY = float(16 * (texture / 16)); float texU_l, texU_r, texV_u, texV_d; AABB& aabb = tile->m_aabb; if (aabb.min.z < 0.0f || aabb.max.z > 1.0f) { texU_l = C_RATIO * (texX); texU_r = C_RATIO * (texX + 15.99f); } // if flipping on the Z coordinate else if (field_8) { texU_r = C_RATIO * (texX + aabb.min.z * 16); texU_l = C_RATIO * (texX + aabb.max.z * 16 - 0.01f); } else { texU_l = C_RATIO * (texX + aabb.min.z * 16); texU_r = C_RATIO * (texX + aabb.max.z * 16 - 0.01f); } if (aabb.min.y < 0.0f || aabb.max.y > 1.0f) { texV_u = C_RATIO * (texY); texV_d = C_RATIO * (texY + 15.99f); } else { texV_u = C_RATIO * (texY + aabb.min.y * 16.0f); texV_d = C_RATIO * (texY + aabb.max.y * 16.0f - 0.01f); } Tesselator& t = Tesselator::instance; if (m_bAmbientOcclusion) { t.color(m_vtxRed[0], m_vtxGreen[0], m_vtxBlue[0]); t.vertexUV(aabb.max.x + x, aabb.min.y + y, aabb.max.z + z, texU_l, texV_d); t.color(m_vtxRed[1], m_vtxGreen[1], m_vtxBlue[1]); t.vertexUV(aabb.max.x + x, aabb.min.y + y, aabb.min.z + z, texU_r, texV_d); t.color(m_vtxRed[2], m_vtxGreen[2], m_vtxBlue[2]); t.vertexUV(aabb.max.x + x, aabb.max.y + y, aabb.min.z + z, texU_r, texV_u); t.color(m_vtxRed[3], m_vtxGreen[3], m_vtxBlue[3]); t.vertexUV(aabb.max.x + x, aabb.max.y + y, aabb.max.z + z, texU_l, texV_u); return; } t.vertexUV(aabb.max.x + x, aabb.min.y + y, aabb.max.z + z, texU_l, texV_d); t.vertexUV(aabb.max.x + x, aabb.min.y + y, aabb.min.z + z, texU_r, texV_d); t.vertexUV(aabb.max.x + x, aabb.max.y + y, aabb.min.z + z, texU_r, texV_u); t.vertexUV(aabb.max.x + x, aabb.max.y + y, aabb.max.z + z, texU_l, texV_u); } void TileRenderer::renderWest(Tile* tile, float x, float y, float z, int texture) { static constexpr float C_RATIO = 1.0f / 256.0f; if (m_textureOverride >= 0) texture = m_textureOverride; float texX = float(16 * (texture % 16)); float texY = float(16 * (texture / 16)); float texU_l, texU_r, texV_u, texV_d; AABB& aabb = tile->m_aabb; if (aabb.min.z < 0.0f || aabb.max.z > 1.0f) { texU_l = C_RATIO * (texX); texU_r = C_RATIO * (texX + 15.99f); } // if flipping on the Z coordinate else if (field_8) { texU_r = C_RATIO * (texX + aabb.min.z * 16); texU_l = C_RATIO * (texX + aabb.max.z * 16 - 0.01f); } else { texU_l = C_RATIO * (texX + aabb.min.z * 16); texU_r = C_RATIO * (texX + aabb.max.z * 16 - 0.01f); } if (aabb.min.y < 0.0f || aabb.max.y>1.0f) { texV_u = C_RATIO * (texY); texV_d = C_RATIO * (texY + 15.99f); } else { texV_u = C_RATIO * (texY + aabb.min.y * 16.0f); texV_d = C_RATIO * (texY + aabb.max.y * 16.0f - 0.01f); } Tesselator& t = Tesselator::instance; if (m_bAmbientOcclusion) { t.color(m_vtxRed[0], m_vtxGreen[0], m_vtxBlue[0]); t.vertexUV(aabb.min.x + x, aabb.max.y + y, aabb.max.z + z, texU_r, texV_u); t.color(m_vtxRed[1], m_vtxGreen[1], m_vtxBlue[1]); t.vertexUV(aabb.min.x + x, aabb.max.y + y, aabb.min.z + z, texU_l, texV_u); t.color(m_vtxRed[2], m_vtxGreen[2], m_vtxBlue[2]); t.vertexUV(aabb.min.x + x, aabb.min.y + y, aabb.min.z + z, texU_l, texV_d); t.color(m_vtxRed[3], m_vtxGreen[3], m_vtxBlue[3]); t.vertexUV(aabb.min.x + x, aabb.min.y + y, aabb.max.z + z, texU_r, texV_d); return; } t.vertexUV(aabb.min.x + x, aabb.max.y + y, aabb.max.z + z, texU_r, texV_u); t.vertexUV(aabb.min.x + x, aabb.max.y + y, aabb.min.z + z, texU_l, texV_u); t.vertexUV(aabb.min.x + x, aabb.min.y + y, aabb.min.z + z, texU_l, texV_d); t.vertexUV(aabb.min.x + x, aabb.min.y + y, aabb.max.z + z, texU_r, texV_d); } void TileRenderer::renderSouth(Tile* tile, float x, float y, float z, int texture) { static constexpr float C_RATIO = 1.0f / 256.0f; if (m_textureOverride >= 0) texture = m_textureOverride; float texX = float(16 * (texture % 16)); float texY = float(16 * (texture / 16)); float texU_l, texU_r, texV_u, texV_d; AABB& aabb = tile->m_aabb; if (aabb.min.x < 0.0f || aabb.max.x > 1.0f) { texU_l = C_RATIO * (texX); texU_r = C_RATIO * (texX + 15.99f); } // if flipping on the X coordinate else if (field_8) { texU_r = C_RATIO * (texX + aabb.min.x * 16); texU_l = C_RATIO * (texX + aabb.max.x * 16 - 0.01f); } else { texU_l = C_RATIO * (texX + aabb.min.x * 16); texU_r = C_RATIO * (texX + aabb.max.x * 16 - 0.01f); } if (aabb.min.y < 0.0f || aabb.max.y>1.0f) { texV_u = C_RATIO * (texY); texV_d = C_RATIO * (texY + 15.99f); } else { texV_u = C_RATIO * (texY + aabb.min.y * 16.0f); texV_d = C_RATIO * (texY + aabb.max.y * 16.0f - 0.01f); } Tesselator& t = Tesselator::instance; if (m_bAmbientOcclusion) { t.color(m_vtxRed[0], m_vtxGreen[0], m_vtxBlue[0]); t.vertexUV(aabb.min.x + x, aabb.max.y + y, aabb.max.z + z, texU_l, texV_u); t.color(m_vtxRed[1], m_vtxGreen[1], m_vtxBlue[1]); t.vertexUV(aabb.min.x + x, aabb.min.y + y, aabb.max.z + z, texU_l, texV_d); t.color(m_vtxRed[2], m_vtxGreen[2], m_vtxBlue[2]); t.vertexUV(aabb.max.x + x, aabb.min.y + y, aabb.max.z + z, texU_r, texV_d); t.color(m_vtxRed[3], m_vtxGreen[3], m_vtxBlue[3]); t.vertexUV(aabb.max.x + x, aabb.max.y + y, aabb.max.z + z, texU_r, texV_u); return; } t.vertexUV(aabb.min.x + x, aabb.max.y + y, aabb.max.z + z, texU_l, texV_u); t.vertexUV(aabb.min.x + x, aabb.min.y + y, aabb.max.z + z, texU_l, texV_d); t.vertexUV(aabb.max.x + x, aabb.min.y + y, aabb.max.z + z, texU_r, texV_d); t.vertexUV(aabb.max.x + x, aabb.max.y + y, aabb.max.z + z, texU_r, texV_u); } void TileRenderer::renderNorth(Tile* tile, float x, float y, float z, int texture) { static constexpr float C_RATIO = 1.0f / 256.0f; if (m_textureOverride >= 0) texture = m_textureOverride; float texX = float(16 * (texture % 16)); float texY = float(16 * (texture / 16)); float texU_l, texU_r, texV_u, texV_d; AABB& aabb = tile->m_aabb; if (aabb.min.x < 0.0f || aabb.max.x > 1.0f) { texU_l = C_RATIO * (texX); texU_r = C_RATIO * (texX + 15.99f); } // if flipping on the X coordinate else if (field_8) { texU_r = C_RATIO * (texX + aabb.min.x * 16); texU_l = C_RATIO * (texX + aabb.max.x * 16 - 0.01f); } else { texU_l = C_RATIO * (texX + aabb.min.x * 16); texU_r = C_RATIO * (texX + aabb.max.x * 16 - 0.01f); } if (aabb.min.y < 0.0f || aabb.max.y>1.0f) { texV_u = C_RATIO * (texY); texV_d = C_RATIO * (texY + 15.99f); } else { texV_u = C_RATIO * (texY + aabb.min.y * 16.0f); texV_d = C_RATIO * (texY + aabb.max.y * 16.0f - 0.01f); } Tesselator& t = Tesselator::instance; if (m_bAmbientOcclusion) { t.color(m_vtxRed[0], m_vtxGreen[0], m_vtxBlue[0]); t.vertexUV(aabb.min.x + x, aabb.max.y + y, aabb.min.z + z, texU_r, texV_u); t.color(m_vtxRed[1], m_vtxGreen[1], m_vtxBlue[1]); t.vertexUV(aabb.max.x + x, aabb.max.y + y, aabb.min.z + z, texU_l, texV_u); t.color(m_vtxRed[2], m_vtxGreen[2], m_vtxBlue[2]); t.vertexUV(aabb.max.x + x, aabb.min.y + y, aabb.min.z + z, texU_l, texV_d); t.color(m_vtxRed[3], m_vtxGreen[3], m_vtxBlue[3]); t.vertexUV(aabb.min.x + x, aabb.min.y + y, aabb.min.z + z, texU_r, texV_d); return; } t.vertexUV(aabb.min.x + x, aabb.max.y + y, aabb.min.z + z, texU_r, texV_u); t.vertexUV(aabb.max.x + x, aabb.max.y + y, aabb.min.z + z, texU_l, texV_u); t.vertexUV(aabb.max.x + x, aabb.min.y + y, aabb.min.z + z, texU_l, texV_d); t.vertexUV(aabb.min.x + x, aabb.min.y + y, aabb.min.z + z, texU_r, texV_d); } void TileRenderer::renderFaceDown(Tile* tile, float x, float y, float z, int texture) { static constexpr float C_RATIO = 1.0f / 256.0f; if (m_textureOverride >= 0) texture = m_textureOverride; float texX = float(16 * (texture % 16)); float texY = float(16 * (texture / 16)); float texU_1, texU_2, texV_1, texV_2; AABB& aabb = tile->m_aabb; if (aabb.min.x >= 0.0f && aabb.max.x <= 1.0f) { texU_1 = C_RATIO * (texX + 16.0f * aabb.min.x); texU_2 = C_RATIO * (texX + 16.0f * aabb.max.x - 0.01f); } else { texU_1 = C_RATIO * (texX); texU_2 = C_RATIO * (texX + 15.99f); } if (aabb.min.z >= 0.0f && aabb.max.z <= 1.0f) { texV_1 = C_RATIO * (texY + 16.0f * aabb.min.z); texV_2 = C_RATIO * (texY + 16.0f * aabb.max.z - 0.01f); } else { texV_1 = C_RATIO * (texY); texV_2 = C_RATIO * (texY + 15.99f); } Tesselator& t = Tesselator::instance; if (m_bAmbientOcclusion) { t.color(m_vtxRed[0], m_vtxGreen[0], m_vtxBlue[0]); t.vertexUV(aabb.max.x + x, aabb.max.y + y, aabb.max.z + z, texU_2, texV_2); t.color(m_vtxRed[1], m_vtxGreen[1], m_vtxBlue[1]); t.vertexUV(aabb.max.x + x, aabb.max.y + y, aabb.min.z + z, texU_2, texV_1); t.color(m_vtxRed[2], m_vtxGreen[2], m_vtxBlue[2]); t.vertexUV(aabb.min.x + x, aabb.max.y + y, aabb.min.z + z, texU_1, texV_1); t.color(m_vtxRed[3], m_vtxGreen[3], m_vtxBlue[3]); t.vertexUV(aabb.min.x + x, aabb.max.y + y, aabb.max.z + z, texU_1, texV_2); return; } t.vertexUV(aabb.max.x + x, aabb.max.y + y, aabb.max.z + z, texU_2, texV_2); t.vertexUV(aabb.max.x + x, aabb.max.y + y, aabb.min.z + z, texU_2, texV_1); t.vertexUV(aabb.min.x + x, aabb.max.y + y, aabb.min.z + z, texU_1, texV_1); t.vertexUV(aabb.min.x + x, aabb.max.y + y, aabb.max.z + z, texU_1, texV_2); } void TileRenderer::renderFaceUp(Tile* tile, float x, float y, float z, int texture) { static constexpr float C_RATIO = 1.0f / 256.0f; if (m_textureOverride >= 0) texture = m_textureOverride; float texX = float(16 * (texture % 16)); float texY = float(16 * (texture / 16)); float texU_1, texU_2, texV_1, texV_2; AABB& aabb = tile->m_aabb; if (aabb.min.x >= 0.0f && aabb.max.x <= 1.0f) { texU_1 = C_RATIO * (texX + 16.0f * aabb.min.x); texU_2 = C_RATIO * (texX + 16.0f * aabb.max.x - 0.01f); } else { texU_1 = C_RATIO * (texX); texU_2 = C_RATIO * (texX + 15.99f); } if (aabb.min.z >= 0.0f && aabb.max.z <= 1.0f) { texV_1 = C_RATIO * (texY + 16.0f * aabb.min.z); texV_2 = C_RATIO * (texY + 16.0f * aabb.max.z - 0.01f); } else { texV_1 = C_RATIO * (texY); texV_2 = C_RATIO * (texY + 15.99f); } Tesselator& t = Tesselator::instance; if (m_bAmbientOcclusion) { t.color(m_vtxRed[0], m_vtxGreen[0], m_vtxBlue[0]); t.vertexUV(aabb.min.x + x, aabb.min.y + y, aabb.max.z + z, texU_1, texV_2); t.color(m_vtxRed[1], m_vtxGreen[1], m_vtxBlue[1]); t.vertexUV(aabb.min.x + x, aabb.min.y + y, aabb.min.z + z, texU_1, texV_1); t.color(m_vtxRed[2], m_vtxGreen[2], m_vtxBlue[2]); t.vertexUV(aabb.max.x + x, aabb.min.y + y, aabb.min.z + z, texU_2, texV_1); t.color(m_vtxRed[3], m_vtxGreen[3], m_vtxBlue[3]); t.vertexUV(aabb.max.x + x, aabb.min.y + y, aabb.max.z + z, texU_2, texV_2); return; } t.vertexUV(aabb.min.x + x, aabb.min.y + y, aabb.max.z + z, texU_1, texV_2); t.vertexUV(aabb.min.x + x, aabb.min.y + y, aabb.min.z + z, texU_1, texV_1); t.vertexUV(aabb.max.x + x, aabb.min.y + y, aabb.min.z + z, texU_2, texV_1); t.vertexUV(aabb.max.x + x, aabb.min.y + y, aabb.max.z + z, texU_2, texV_2); } void TileRenderer::tesselateCrossTexture(Tile* tile, int data, float x, float y, float z) { static constexpr float C_RATIO = 1.0f / 256.0f; int texture = m_textureOverride; if (texture < 0) texture = tile->getTexture(DIR_YNEG, data); float texX = float(16 * (texture % 16)); float texY = float(16 * (texture / 16)); // calculate U and V coordinates float texU_l = texX * C_RATIO, texU_r = (texX + 15.99f) * C_RATIO; float texV_u = texY * C_RATIO, texV_d = (texY + 15.99f) * C_RATIO; float cenX = x + 0.5f, cenZ = z + 0.5f; float x1 = cenX - 0.45f, x2 = cenX + 0.45f; float z1 = cenZ - 0.45f, z2 = cenZ + 0.45f; Tesselator& t = Tesselator::instance; // face 1 t.vertexUV(x1, y + 1, z1, texU_l, texV_u); t.vertexUV(x1, y + 0, z1, texU_l, texV_d); t.vertexUV(x2, y + 0, z2, texU_r, texV_d); t.vertexUV(x2, y + 1, z2, texU_r, texV_u); // face 2 t.vertexUV(x2, y + 1, z2, texU_l, texV_u); t.vertexUV(x2, y + 0, z2, texU_l, texV_d); t.vertexUV(x1, y + 0, z1, texU_r, texV_d); t.vertexUV(x1, y + 1, z1, texU_r, texV_u); // face 3 t.vertexUV(x1, y + 1, z2, texU_l, texV_u); t.vertexUV(x1, y + 0, z2, texU_l, texV_d); t.vertexUV(x2, y + 0, z1, texU_r, texV_d); t.vertexUV(x2, y + 1, z1, texU_r, texV_u); // face 4 t.vertexUV(x2, y + 1, z1, texU_l, texV_u); t.vertexUV(x2, y + 0, z1, texU_l, texV_d); t.vertexUV(x1, y + 0, z2, texU_r, texV_d); t.vertexUV(x1, y + 1, z2, texU_r, texV_u); } bool TileRenderer::tesselateBlockInWorld(Tile* tile, int x, int y, int z, float r, float g, float b) { float topR = r, topG = g, topB = b; if (tile == Tile::grass) r = g = b = 1.0f; Tesselator& t = Tesselator::instance; float fLightHere = tile->getBrightness(m_pLevelSource, x, y, z); bool bDrewAnything = false; if (m_bDisableCulling || tile->shouldRenderFace(m_pLevelSource, x, y - 1, z, DIR_YNEG)) { bDrewAnything = true; float fLight = tile->getBrightness(m_pLevelSource, x, y - 1, z); t.color(r * 0.5f * fLight, g * 0.5f * fLight, b * 0.5f * fLight); renderFaceUp(tile, float(x), float(y), float(z), tile->getTexture(m_pLevelSource, x, y, z, DIR_YNEG)); } if (m_bDisableCulling || tile->shouldRenderFace(m_pLevelSource, x, y + 1, z, DIR_YPOS)) { bDrewAnything = true; float fLight = tile->getBrightness(m_pLevelSource, x, y + 1, z); if (tile->m_aabb.max.y != 1.0f && !tile->m_pMaterial->isLiquid()) fLight = fLightHere; t.color(topR * fLight, topG * fLight, topB * fLight); renderFaceDown(tile, float(x), float(y), float(z), tile->getTexture(m_pLevelSource, x, y, z, DIR_YPOS)); } if (m_bDisableCulling || tile->shouldRenderFace(m_pLevelSource, x, y, z - 1, DIR_ZNEG)) { bDrewAnything = true; float fLight = tile->getBrightness(m_pLevelSource, x, y, z - 1); if (tile->m_aabb.min.z > 0.0f) fLight = fLightHere; t.color(r * 0.8f * fLight, g * 0.8f * fLight, b * 0.8f * fLight); int texture = tile->getTexture(m_pLevelSource, x, y, z, DIR_ZNEG); renderNorth(tile, float(x), float(y), float(z), texture); if (m_bFancyGrass && texture == TEXTURE_GRASS_SIDE && this->m_textureOverride < 0) { t.color(topR * 0.8f * fLight, topG * 0.8f * fLight, topB * 0.8f * fLight); renderNorth(tile, float(x), float(y), float(z), TEXTURE_NONE38); } } if (m_bDisableCulling || tile->shouldRenderFace(m_pLevelSource, x, y, z + 1, DIR_ZPOS)) { bDrewAnything = true; float fLight = tile->getBrightness(m_pLevelSource, x, y, z + 1); if (tile->m_aabb.max.z < 1.0f) fLight = fLightHere; t.color(r * 0.8f * fLight, g * 0.8f * fLight, b * 0.8f * fLight); int texture = tile->getTexture(m_pLevelSource, x, y, z, DIR_ZPOS); renderSouth(tile, float(x), float(y), float(z), texture); if (m_bFancyGrass && texture == TEXTURE_GRASS_SIDE && this->m_textureOverride < 0) { t.color(topR * 0.8f * fLight, topG * 0.8f * fLight, topB * 0.8f * fLight); renderSouth(tile, float(x), float(y), float(z), TEXTURE_NONE38); } } if (m_bDisableCulling || tile->shouldRenderFace(m_pLevelSource, x - 1, y, z, DIR_XNEG)) { bDrewAnything = true; float fLight = tile->getBrightness(m_pLevelSource, x - 1, y, z); if (tile->m_aabb.min.x > 0.0f) fLight = fLightHere; t.color(r * 0.6f * fLight, g * 0.6f * fLight, b * 0.6f * fLight); int texture = tile->getTexture(m_pLevelSource, x, y, z, DIR_XNEG); renderWest(tile, float(x), float(y), float(z), texture); if (m_bFancyGrass && texture == TEXTURE_GRASS_SIDE && this->m_textureOverride < 0) { t.color(topR * 0.6f * fLight, topG * 0.6f * fLight, topB * 0.6f * fLight); renderWest(tile, float(x), float(y), float(z), TEXTURE_NONE38); } } if (m_bDisableCulling || tile->shouldRenderFace(m_pLevelSource, x + 1, y, z, DIR_XPOS)) { bDrewAnything = true; float fLight = tile->getBrightness(m_pLevelSource, x + 1, y, z); if (tile->m_aabb.max.x < 1.0f) fLight = fLightHere; t.color(r * 0.6f * fLight, g * 0.6f * fLight, b * 0.6f * fLight); int texture = tile->getTexture(m_pLevelSource, x, y, z, DIR_XPOS); renderEast(tile, float(x), float(y), float(z), texture); if (m_bFancyGrass && texture == TEXTURE_GRASS_SIDE && this->m_textureOverride < 0) { t.color(topR * 0.6f * fLight, topG * 0.6f * fLight, topB * 0.6f * fLight); renderEast(tile, float(x), float(y), float(z), TEXTURE_NONE38); } } return bDrewAnything; } bool TileRenderer::tesselateBlockInWorld(Tile* tile, int x, int y, int z) { int color = getTileColor(tile, x, y, z); float r = float(GET_RED (color)) / 255.0f; float g = float(GET_GREEN(color)) / 255.0f; float b = float(GET_BLUE (color)) / 255.0f; if (Minecraft::useAmbientOcclusion) { #ifdef ENH_USE_OWN_AO return tesselateBlockInWorldWithAmbienceOcclusionV2(tile, x, y, z, r, g, b); #else return tesselateBlockInWorldWithAmbienceOcclusion(tile, x, y, z, r, g, b); #endif } return tesselateBlockInWorld(tile, x, y, z, r, g, b); } bool TileRenderer::tesselateCrossInWorld(Tile* tile, int x, int y, int z) { Tesselator& t = Tesselator::instance; float bright = tile->getBrightness(m_pLevelSource, x, y, z); t.color(bright, bright, bright); tesselateCrossTexture(tile, m_pLevelSource->getData(x, y, z), float(x), float(y), float(z)); return true; } bool TileRenderer::tesselateWaterInWorld(Tile* tile1, int x, int y, int z) { constexpr float C_RATIO = 1.0f / 256.0f; LiquidTile* tile = (LiquidTile*)tile1; bool bRenderFaceDown, bRenderFaceUp, bRenderSides[4]; Tesselator& t = Tesselator::instance; bRenderFaceDown = tile->shouldRenderFace(m_pLevelSource, x, y + 1, z, DIR_YPOS); bRenderFaceUp = tile->shouldRenderFace(m_pLevelSource, x, y - 1, z, DIR_YNEG); bRenderSides[0] = tile->shouldRenderFace(m_pLevelSource, x, y, z - 1, DIR_ZNEG); bRenderSides[1] = tile->shouldRenderFace(m_pLevelSource, x, y, z + 1, DIR_ZPOS); bRenderSides[2] = tile->shouldRenderFace(m_pLevelSource, x - 1, y, z, DIR_XNEG); bRenderSides[3] = tile->shouldRenderFace(m_pLevelSource, x + 1, y, z, DIR_XPOS); if (!bRenderFaceDown && !bRenderFaceUp && !bRenderSides[0] && !bRenderSides[1] && !bRenderSides[2] && !bRenderSides[3]) return false; int tileData = m_pLevelSource->getData(x, y, z); float fHeight1 = getWaterHeight(x, y, z, tile->m_pMaterial), fHeight2 = getWaterHeight(x, y, z + 1, tile->m_pMaterial), fHeight3 = getWaterHeight(x + 1, y, z + 1, tile->m_pMaterial), fHeight4 = getWaterHeight(x + 1, y, z, tile->m_pMaterial); // @TODO: fix gotos bool bFlag1, bFlag2; if (!m_bDisableCulling) { bFlag1 = bRenderFaceDown; if (!bRenderFaceDown) { if (!bRenderFaceUp) goto label_8; goto label_6; } } { // @NOTE: Have to use tile1 because for whatever reason MSVC doesn't think an overload // for `tile` exists that takes 2 int arguments int texFaceDown = tile->getTexture(DIR_YPOS, tileData); float slopeAngle = tile->getSlopeAngle(m_pLevelSource, x, y, z, tile->m_pMaterial); int texX, texY; if (slopeAngle > -999.0f) { int texNorth = tile->getTexture(DIR_ZNEG, tileData); texX = texNorth & 0xF0; texY = (texNorth & 0xF) * 16; } else { texX = texFaceDown & 0xF0; texY = (texFaceDown & 0xF) * 16; } float texUV_1, texUV_2, texUV_3, texUV_4, texUV_5, texUV_6, texUV_7, texUV_8; if (slopeAngle >= -999.0f) { texUV_1 = float(texY + 16) * C_RATIO; texUV_2 = float(texX + 16) * C_RATIO; } else { slopeAngle = 0.0f; texUV_1 = float(texY + 8) * C_RATIO; texUV_2 = float(texX + 8) * C_RATIO; } texUV_3 = C_RATIO * 8.0f * Mth::sin(slopeAngle); texUV_4 = C_RATIO * 8.0f * Mth::cos(slopeAngle); float bright = tile->getBrightness(m_pLevelSource, x, y, z); texUV_5 = texUV_1 - texUV_4; texUV_6 = texUV_2 - texUV_4; t.color(bright, bright, bright); texUV_7 = texUV_2 + texUV_4; texUV_8 = texUV_1 + texUV_4; t.vertexUV(x + 0.0f, y + fHeight1, z + 0.0f, (texUV_1 - texUV_4) - texUV_3, texUV_6 + texUV_3); t.vertexUV(x + 0.0f, y + fHeight2, z + 1.0f, texUV_3 + texUV_5, texUV_7 + texUV_3); t.vertexUV(x + 1.0f, y + fHeight3, z + 1.0f, texUV_8 + texUV_3, texUV_7 - texUV_3); t.vertexUV(x + 1.0f, y + fHeight4, z + 0.0f, texUV_8 - texUV_3, texUV_6 - texUV_3); } if (m_bDisableCulling) goto label_7; bFlag1 = true; if (bRenderFaceUp) { label_6: label_7: float bright = tile->getBrightness(m_pLevelSource, x, y - 1, z); t.color(bright * 0.5f, bright * 0.5f, bright * 0.5f); renderFaceUp(tile1, float(x), float(y), float(z), tile->getTexture(DIR_YNEG)); bFlag1 = true; } label_8: bFlag2 = bFlag1; //bool bRenderedSides = false; for (int dir = 0; dir < 4; dir++) { int checkX = x, checkZ = z; switch (dir) { case 0: checkZ--; break; case 1: checkZ++; break; case 2: checkX--; break; case 3: checkX++; break; } int texture = tile1->getTexture(dir + DIR_ZNEG, tileData); if (!m_bDisableCulling && !bRenderSides[dir]) continue; float vtxX1, vtxX2, vtxZ1, vtxZ2, height1, height2; switch (dir) { case 0: { vtxX1 = float(x); vtxX2 = float(x + 1); vtxZ1 = float(z); vtxZ2 = float(z); height1 = fHeight1; height2 = fHeight4; break; } case 1: { vtxX1 = float(x + 1); vtxX2 = float(x); vtxZ1 = float(z + 1); vtxZ2 = float(z + 1); height1 = fHeight3; height2 = fHeight2; break; } case 2: { vtxX1 = float(x); vtxX2 = float(x); vtxZ1 = float(z + 1); vtxZ2 = float(z); height1 = fHeight2; height2 = fHeight1; break; } case 3: { vtxX1 = float(x + 1); vtxX2 = float(x + 1); vtxZ1 = float(z); vtxZ2 = float(z + 1); height1 = fHeight4; height2 = fHeight3; break; } } float texU_1, texU_2, texV_1, texV_2, texV_3; int texX = (texture & 0xF) * 16; int texY = (texture >> 4) * 16; texU_1 = C_RATIO * float(texX); texU_2 = C_RATIO * (float(texX) + 15.99f); texV_1 = C_RATIO * (float(texY) + (1.0f - height1) * 16.0f); texV_2 = C_RATIO * (float(texY) + (1.0f - height2) * 16.0f); texV_3 = C_RATIO * (float(texY + 16.0f) - 0.01f); bFlag2 = true; //bRenderedSides = true; float brightMul = dir >= DIR_XNEG ? 0.6f : 0.8f; float bright = tile->getBrightness(m_pLevelSource, checkX, y, checkZ); t.color(bright* brightMul, bright* brightMul, bright* brightMul); t.vertexUV(vtxX1, float(y) + height1, vtxZ1, texU_1, texV_1); t.vertexUV(vtxX2, float(y) + height2, vtxZ2, texU_2, texV_2); t.vertexUV(vtxX2, float(y) + 0.0f, vtxZ2, texU_2, texV_3); t.vertexUV(vtxX1, float(y) + 0.0f, vtxZ1, texU_1, texV_3); } tile->m_aabb.min.y = 0.0f; tile->m_aabb.max.y = 1.0f; return bFlag2; } #ifdef ENH_FIX_INVIS_STAIRS #define PROC_RESULT(x) bRenderedAnything = (x) || bRenderedAnything; #else #define PROC_RESULT(x) (x) #endif bool TileRenderer::tesselateStairsInWorld(Tile* tile, int x, int y, int z) { bool bRenderedAnything = false; switch (m_pLevelSource->getData(x, y, z)) { case 0: { tile->setShape(0.0f, 0.0f, 0.0f, 0.5f, 0.5f, 1.0f); PROC_RESULT(tesselateBlockInWorld(tile, x, y, z)); tile->setShape(0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f); PROC_RESULT(tesselateBlockInWorld(tile, x, y, z)); break; } case 1: { tile->setShape(0.0f, 0.0f, 0.0f, 0.5f, 1.0f, 1.0f); PROC_RESULT(tesselateBlockInWorld(tile, x, y, z)); tile->setShape(0.5f, 0.0f, 0.0f, 1.0f, 0.5f, 1.0f); PROC_RESULT(tesselateBlockInWorld(tile, x, y, z)); break; } case 2: { tile->setShape(0.0f, 0.0f, 0.0f, 1.0f, 0.5f, 0.5f); PROC_RESULT(tesselateBlockInWorld(tile, x, y, z)); tile->setShape(0.0f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f); PROC_RESULT(tesselateBlockInWorld(tile, x, y, z)); break; } case 3: { tile->setShape(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f); PROC_RESULT(tesselateBlockInWorld(tile, x, y, z)); tile->setShape(0.0f, 0.0f, 0.5f, 1.0f, 0.5f, 1.0f); PROC_RESULT(tesselateBlockInWorld(tile, x, y, z)); break; } } tile->setShape(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f); // @BUG: In a chunk that only contains stairs, everything will be invisible, because this // function returns 0. return bRenderedAnything; } bool TileRenderer::tesselateDoorInWorld(Tile* tile, int x, int y, int z) { Tesselator& t = Tesselator::instance; float fBrightHere = tile->getBrightness(m_pLevelSource, x, y, z), fBright; int texture; fBright = tile->getBrightness(m_pLevelSource, x, y - 1, z); if (tile->m_aabb.min.y > 0.0f) fBright = fBrightHere; if (Tile::lightEmission[tile->m_ID]) fBright = 1.0f; t.color(fBright * 0.5f, fBright * 0.5f, fBright * 0.5f); renderFaceUp(tile, float(x), float(y), float(z), tile->getTexture(m_pLevelSource, x, y, z, DIR_YNEG)); fBright = tile->getBrightness(m_pLevelSource, x, y + 1, z); if (tile->m_aabb.max.y < 1.0f) fBright = fBrightHere; if (Tile::lightEmission[tile->m_ID]) fBright = 1.0f; t.color(fBright, fBright, fBright); renderFaceDown(tile, float(x), float(y), float(z), tile->getTexture(m_pLevelSource, x, y, z, DIR_YPOS)); fBright = tile->getBrightness(m_pLevelSource, x, y, z - 1); if (tile->m_aabb.min.z > 0.0f) fBright = fBrightHere; if (Tile::lightEmission[tile->m_ID]) fBright = 1.0f; t.color(fBright * 0.8f, fBright * 0.8f, fBright * 0.8f); texture = tile->getTexture(m_pLevelSource, x, y, z, DIR_ZNEG); if (texture < 0) texture = -texture, field_8 = true; renderNorth(tile, float(x), float(y), float(z), texture); field_8 = false; fBright = tile->getBrightness(m_pLevelSource, x, y, z + 1); if (tile->m_aabb.max.z < 1.0f) fBright = fBrightHere; if (Tile::lightEmission[tile->m_ID]) fBright = 1.0f; t.color(fBright * 0.8f, fBright * 0.8f, fBright * 0.8f); texture = tile->getTexture(m_pLevelSource, x, y, z, DIR_ZPOS); if (texture < 0) texture = -texture, field_8 = true; renderSouth(tile, float(x), float(y), float(z), texture); field_8 = false; fBright = tile->getBrightness(m_pLevelSource, x - 1, y, z); if (tile->m_aabb.min.x > 0.0f) fBright = fBrightHere; if (Tile::lightEmission[tile->m_ID]) fBright = 1.0f; t.color(fBright * 0.6f, fBright * 0.6f, fBright * 0.6f); texture = tile->getTexture(m_pLevelSource, x, y, z, DIR_XNEG); if (texture < 0) texture = -texture, field_8 = true; renderWest(tile, float(x), float(y), float(z), texture); field_8 = false; fBright = tile->getBrightness(m_pLevelSource, x + 1, y, z); if (tile->m_aabb.max.x < 1.0f) fBright = fBrightHere; if (Tile::lightEmission[tile->m_ID]) fBright = 1.0f; t.color(fBright * 0.6f, fBright * 0.6f, fBright * 0.6f); texture = tile->getTexture(m_pLevelSource, x, y, z, DIR_XPOS); if (texture < 0) texture = -texture, field_8 = true; renderEast(tile, float(x), float(y), float(z), texture); field_8 = false; return true; } void TileRenderer::tesselateTorch(Tile* tile, float x, float y, float z, float a, float b) { constexpr float C_RATIO = 1.0f / 256.0f; constexpr float C_ONE_PIXEL = 1.0f / 16.0f; constexpr float C_HALF_TILE = 1.0f / 2.0f; constexpr float C_UNK_1 = 0.375f; int texture = tile->getTexture(DIR_YNEG); if (m_textureOverride >= 0) texture = m_textureOverride; // @TODO: Clean up a bit float texX = float(16 * (texture % 16)); float texY = float(16 * (texture / 16)); float texU_1 = texX * C_RATIO; float texU_2 = (texX + 15.99f) * C_RATIO; float texV_1 = (texY * C_RATIO) + 1.0f / 32.0f; float texV_2 = (texY + 15.99f) * C_RATIO; float x1 = x + 0.5f, z1 = z + 0.5f; float z2 = z1 + (float)(b * C_UNK_1); Tesselator& t = Tesselator::instance; float x_1 = (x1 + (a * C_UNK_1)) - C_ONE_PIXEL; float x_2 = (x1 + (a * C_UNK_1)) + C_ONE_PIXEL; float x_3 = x1 - C_ONE_PIXEL; float x_4 = x1 + C_ONE_PIXEL; float x_5 = x1 - C_HALF_TILE; float x_6 = x1 + C_HALF_TILE; float x_7 = x_6 + a; float x_8 = x_3 + a; float x_9 = x_4 + a; float x_0 = x_5 + a; float y_1 = y + C_ONE_PIXEL * 10.0f; float y_2 = y + 1.0f; float y_3 = y + 0.0f; float z_1 = z2 - C_ONE_PIXEL; float z_2 = z2 + C_ONE_PIXEL; float z_3 = z1 - 0.5f; float z_4 = z1 + 0.5f; float z_5 = z1 - C_ONE_PIXEL; float z_6 = z1 + C_ONE_PIXEL; float z_7 = z_3 + b; float z_8 = z_4 + b; float z_9 = z_5 + b; float z_0 = z_6 + b; float texU_3 = texU_1 + 0.027344f; float texU_4 = texU_1 + 0.035156f; float texV_3 = texY * C_RATIO; float texV_4 = texY * C_RATIO + 0.023438f; t.vertexUV(x_1, y_1, z_1, texU_3, texV_4); t.vertexUV(x_1, y_1, z_2, texU_3, texV_1); t.vertexUV(x_2, y_1, z_2, texU_4, texV_1); t.vertexUV(x_2, y_1, z_1, texU_4, texV_4); t.vertexUV(x_3, y_2, z_3, texU_1, texV_3); t.vertexUV(x_8, y_3, z_7, texU_1, texV_2); t.vertexUV(x_8, y_3, z_8, texU_2, texV_2); t.vertexUV(x_3, y_2, z_4, texU_2, texV_3); t.vertexUV(x_4, y_2, z_4, texU_1, texV_3); t.vertexUV(x_9, y_3, z_8, texU_1, texV_2); t.vertexUV(x_9, y_3, z_7, texU_2, texV_2); t.vertexUV(x_4, y_2, z_3, texU_2, texV_3); t.vertexUV(x_5, y_2, z_6, texU_1, texV_3); t.vertexUV(x_0, y_3, z_0, texU_1, texV_2); t.vertexUV(x_7, y_3, z_0, texU_2, texV_2); t.vertexUV(x_6, y_2, z_6, texU_2, texV_3); t.vertexUV(x_6, y_2, z_5, texU_1, texV_3); t.vertexUV(x_7, y_3, z_9, texU_1, texV_2); t.vertexUV(x_0, y_3, z_9, texU_2, texV_2); t.vertexUV(x_5, y_2, z_5, texU_2, texV_3); } bool TileRenderer::tesselateTorchInWorld(Tile* tile, int x, int y, int z) { int data = m_pLevelSource->getData(x, y, z); float bright = tile->getBrightness(m_pLevelSource, x, y, z); if (Tile::lightEmission[tile->m_ID] > 0) bright = 1.0f; Tesselator& t = Tesselator::instance; t.color(bright, bright, bright); switch (data) { case 1: tesselateTorch(tile, float(x) - 0.1f, float(y) + 0.2f, float(z), -0.4f, 0.0f); break; case 2: tesselateTorch(tile, float(x) + 0.1f, float(y) + 0.2f, float(z), 0.4f, 0.0f); break; case 3: tesselateTorch(tile, float(x), float(y) + 0.2f, float(z) - 0.1f, 0.0f, -0.4f); break; case 4: tesselateTorch(tile, float(x), float(y) + 0.2f, float(z) + 0.1f, 0.0f, 0.4f); break; default: tesselateTorch(tile, float(x), float(y), float(z), 0.0f, 0.0f); break; } return true; } bool TileRenderer::tesselateLadderInWorld(Tile* tile, int x, int y, int z) { constexpr float C_RATIO = 1.0f / 256.0f; Tesselator& t = Tesselator::instance; int texture = tile->getTexture(DIR_YNEG); if (m_textureOverride >= 0) texture = m_textureOverride; float bright = m_pLevelSource->getBrightness(x, y, z); t.color(bright, bright, bright); float texX = float(16 * (texture % 16)); float texY = float(16 * (texture / 16)); float texU_1 = C_RATIO * texX; float texU_2 = C_RATIO * (texX + 15.99f); float texV_1 = C_RATIO * texY; float texV_2 = C_RATIO * (texY + 15.99f); switch (m_pLevelSource->getData(x, y, z)) { case 2: t.vertexUV(float(x + 1), float(y + 1), float(z + 1) - 0.05f, texU_1, texV_1); t.vertexUV(float(x + 1), float(y + 0), float(z + 1) - 0.05f, texU_1, texV_2); t.vertexUV(float(x + 0), float(y + 0), float(z + 1) - 0.05f, texU_2, texV_2); t.vertexUV(float(x + 0), float(y + 1), float(z + 1) - 0.05f, texU_2, texV_1); break; case 3: t.vertexUV(float(x + 1), float(y + 0), float(z) + 0.05f, texU_2, texV_2); t.vertexUV(float(x + 1), float(y + 1), float(z) + 0.05f, texU_2, texV_1); t.vertexUV(float(x + 0), float(y + 1), float(z) + 0.05f, texU_1, texV_1); t.vertexUV(float(x + 0), float(y + 0), float(z) + 0.05f, texU_1, texV_2); break; case 4: t.vertexUV(float(x + 1) - 0.05f, float(y + 0), float(z + 1), texU_2, texV_2); t.vertexUV(float(x + 1) - 0.05f, float(y + 1), float(z + 1), texU_2, texV_1); t.vertexUV(float(x + 1) - 0.05f, float(y + 1), float(z + 0), texU_1, texV_1); t.vertexUV(float(x + 1) - 0.05f, float(y + 0), float(z + 0), texU_1, texV_2); break; case 5: t.vertexUV(float(x) + 0.05f, float(y + 1), float(z + 1), texU_1, texV_1); t.vertexUV(float(x) + 0.05f, float(y + 0), float(z + 1), texU_1, texV_2); t.vertexUV(float(x) + 0.05f, float(y + 0), float(z + 0), texU_2, texV_2); t.vertexUV(float(x) + 0.05f, float(y + 1), float(z + 0), texU_2, texV_1); break; } return true; } bool TileRenderer::tesselateFireInWorld(Tile* tile, int x, int y, int z) { constexpr float C_RATIO = 1.0f / 256.0f; Tesselator& t = Tesselator::instance; int texture = tile->getTexture(DIR_YNEG); float bright = tile->getBrightness(m_pLevelSource, x, y, z); t.color(bright, bright, bright); FireTile* pFireTile = (FireTile*)Tile::fire; float texX = float(16 * (texture % 16)); float texY = float(16 * (texture / 16)); float texU_1 = C_RATIO * (texX); float texU_2 = C_RATIO * (texX + 15.99f); float texV_1 = C_RATIO * (texY); float texV_2 = C_RATIO * (texY + 15.99f); float xf = float(x), yf = float(y), zf = float(z); if (m_pLevelSource->isSolidTile(x, y - 1, z) || pFireTile->canBurn(m_pLevelSource, x, y - 1, z)) { t.vertexUV(xf + 0.5f - 0.3f, yf + 1.4f, zf + 1.0f, texU_2, texV_1); t.vertexUV(xf + 0.5f + 0.2f, yf + 0.0f, zf + 1.0f, texU_2, texV_2); t.vertexUV(xf + 0.5f + 0.2f, yf + 0.0f, zf + 0.0f, texU_1, texV_2); t.vertexUV(xf + 0.5f - 0.3f, yf + 1.4f, zf + 0.0f, texU_1, texV_1); t.vertexUV(xf + 0.5f + 0.3f, yf + 1.4f, zf + 0.0f, texU_2, texV_1); t.vertexUV(xf + 0.5f - 0.2f, yf + 0.0f, zf + 0.0f, texU_2, texV_2); t.vertexUV(xf + 0.5f - 0.2f, yf + 0.0f, zf + 1.0f, texU_1, texV_2); t.vertexUV(xf + 0.5f + 0.3f, yf + 1.4f, zf + 1.0f, texU_1, texV_1); t.vertexUV(xf + 1.0f, yf + 1.4f, zf + 0.5f + 0.3f, texU_2, texV_1); t.vertexUV(xf + 1.0f, yf + 0.0f, zf + 0.5f - 0.2f, texU_2, texV_2); t.vertexUV(xf + 0.0f, yf + 0.0f, zf + 0.5f - 0.2f, texU_1, texV_2); t.vertexUV(xf + 0.0f, yf + 1.4f, zf + 0.5f + 0.3f, texU_1, texV_1); t.vertexUV(xf + 0.0f, yf + 1.4f, zf + 0.5f - 0.3f, texU_2, texV_1); t.vertexUV(xf + 0.0f, yf + 0.0f, zf + 0.5f + 0.2f, texU_2, texV_2); t.vertexUV(xf + 1.0f, yf + 0.0f, zf + 0.5f + 0.2f, texU_1, texV_2); t.vertexUV(xf + 1.0f, yf + 1.4f, zf + 0.5f - 0.3f, texU_1, texV_1); t.vertexUV(xf + 0.5f - 0.4f, yf + 1.4f, zf + 0.0f, texU_1, texV_1); t.vertexUV(xf + 0.5f - 0.5f, yf + 0.0f, zf + 0.0f, texU_1, texV_2); t.vertexUV(xf + 0.5f - 0.5f, yf + 0.0f, zf + 1.0f, texU_2, texV_2); t.vertexUV(xf + 0.5f - 0.4f, yf + 1.4f, zf + 1.0f, texU_2, texV_1); t.vertexUV(xf + 0.5f + 0.4f, yf + 1.4f, zf + 1.0f, texU_1, texV_1); t.vertexUV(xf + 0.5f + 0.5f, yf + 0.0f, zf + 1.0f, texU_1, texV_2); t.vertexUV(xf + 0.5f + 0.5f, yf + 0.0f, zf + 0.0f, texU_2, texV_2); t.vertexUV(xf + 0.5f + 0.4f, yf + 1.4f, zf + 0.0f, texU_2, texV_1); t.vertexUV(xf + 0.0f, yf + 1.4f, zf + 0.5f + 0.4f, texU_1, texV_1); t.vertexUV(xf + 0.0f, yf + 0.0f, zf + 0.5f + 0.5f, texU_1, texV_2); t.vertexUV(xf + 1.0f, yf + 0.0f, zf + 0.5f + 0.5f, texU_2, texV_2); t.vertexUV(xf + 1.0f, yf + 1.4f, zf + 0.5f + 0.4f, texU_2, texV_1); t.vertexUV(xf + 1.0f, yf + 1.4f, zf + 0.5f - 0.4f, texU_1, texV_1); t.vertexUV(xf + 1.0f, yf + 0.0f, zf + 0.5f - 0.5f, texU_1, texV_2); t.vertexUV(xf + 0.0f, yf + 0.0f, zf + 0.5f - 0.5f, texU_2, texV_2); t.vertexUV(xf + 0.0f, yf + 1.4f, zf + 0.5f - 0.4f, texU_2, texV_1); return true; } if (((y / 2 + x / 2 + z / 2) & 1) == 0) std::swap(texU_1, texU_2); if (pFireTile->canBurn(m_pLevelSource, x - 1, y, z)) { t.vertexUV(xf + 0.2f, (yf + 1.4f) + 0.0625f, zf + 1.0f, texU_1, texV_1); t.vertexUV(xf + 0.0f, (yf + 0.0f) + 0.0625f, zf + 1.0f, texU_1, texV_2); t.vertexUV(xf + 0.0f, (yf + 0.0f) + 0.0625f, zf + 0.0f, texU_2, texV_2); t.vertexUV(xf + 0.2f, (yf + 1.4f) + 0.0625f, zf + 0.0f, texU_2, texV_1); t.vertexUV(xf + 0.2f, (yf + 1.4f) + 0.0625f, zf + 0.0f, texU_2, texV_1); t.vertexUV(xf + 0.0f, (yf + 0.0f) + 0.0625f, zf + 0.0f, texU_2, texV_2); t.vertexUV(xf + 0.0f, (yf + 0.0f) + 0.0625f, zf + 1.0f, texU_1, texV_2); t.vertexUV(xf + 0.2f, (yf + 1.4f) + 0.0625f, zf + 1.0f, texU_1, texV_1); } if (pFireTile->canBurn(m_pLevelSource, x + 1, y, z)) { t.vertexUV(xf + 1.0f - 0.2f, (y + 1.4f) + 0.0625f, z + 0.0f, texU_2, texV_1); t.vertexUV(xf + 1.0f + 0.0f, (y + 0.0f) + 0.0625f, z + 0.0f, texU_2, texV_2); t.vertexUV(xf + 1.0f + 0.0f, (y + 0.0f) + 0.0625f, z + 1.0f, texU_1, texV_2); t.vertexUV(xf + 1.0f - 0.2f, (y + 1.4f) + 0.0625f, z + 1.0f, texU_1, texV_1); t.vertexUV(xf + 1.0f - 0.2f, (y + 1.4f) + 0.0625f, z + 1.0f, texU_1, texV_1); t.vertexUV(xf + 1.0f + 0.0f, (y + 0.0f) + 0.0625f, z + 1.0f, texU_1, texV_2); t.vertexUV(xf + 1.0f + 0.0f, (y + 0.0f) + 0.0625f, z + 0.0f, texU_2, texV_2); t.vertexUV(xf + 1.0f - 0.2f, (y + 1.4f) + 0.0625f, z + 0.0f, texU_2, texV_1); } if (pFireTile->canBurn(m_pLevelSource, x, y, z - 1)) { t.vertexUV(x + 0.0f, (y + 1.4f) + 0.0625f, z + 0.2f, texU_1, texV_1); t.vertexUV(x + 0.0f, (y + 0.0f) + 0.0625f, z + 0.0f, texU_1, texV_2); t.vertexUV(x + 1.0f, (y + 0.0f) + 0.0625f, z + 0.0f, texU_2, texV_2); t.vertexUV(x + 1.0f, (y + 1.4f) + 0.0625f, z + 0.2f, texU_2, texV_1); t.vertexUV(x + 1.0f, (y + 1.4f) + 0.0625f, z + 0.2f, texU_2, texV_1); t.vertexUV(x + 1.0f, (y + 0.0f) + 0.0625f, z + 0.0f, texU_2, texV_2); t.vertexUV(x + 0.0f, (y + 0.0f) + 0.0625f, z + 0.0f, texU_1, texV_2); t.vertexUV(x + 0.0f, (y + 1.4f) + 0.0625f, z + 0.2f, texU_1, texV_1); } if (pFireTile->canBurn(m_pLevelSource, x, y, z + 1)) { t.vertexUV(x + 1.0f, (y + 1.4f) + 0.0625f, z + 1.0f - 0.2f, texU_2, texV_1); t.vertexUV(x + 1.0f, (y + 0.0f) + 0.0625f, z + 1.0f + 0.0f, texU_2, texV_2); t.vertexUV(x + 0.0f, (y + 0.0f) + 0.0625f, z + 1.0f + 0.0f, texU_1, texV_2); t.vertexUV(x + 0.0f, (y + 1.4f) + 0.0625f, z + 1.0f - 0.2f, texU_1, texV_1); t.vertexUV(x + 0.0f, (y + 1.4f) + 0.0625f, z + 1.0f - 0.2f, texU_1, texV_1); t.vertexUV(x + 0.0f, (y + 0.0f) + 0.0625f, z + 1.0f + 0.0f, texU_1, texV_2); t.vertexUV(x + 1.0f, (y + 0.0f) + 0.0625f, z + 1.0f + 0.0f, texU_2, texV_2); t.vertexUV(x + 1.0f, (y + 1.4f) + 0.0625f, z + 1.0f - 0.2f, texU_2, texV_1); } if (pFireTile->canBurn(m_pLevelSource, x, y + 1, z)) { // @NOTE: Converting z and x to uint8_t for whatever reason if (((uint8_t(z) + uint8_t(x) + y + 1) & 1) != 0) { float y1f = float(y + 1); t.vertexUV(xf + 0.0f, y1f - 0.2f, zf + 0.5f + 0.5f, texU_2, texV_1); t.vertexUV(xf + 0.0f, y1f + 0.0f, zf + 0.5f - 0.5f, texU_2, texV_2); t.vertexUV(xf + 1.0f, y1f + 0.0f, zf + 0.5f - 0.5f, texU_1, texV_2); t.vertexUV(xf + 1.0f, y1f - 0.2f, zf + 0.5f + 0.5f, texU_1, texV_1); t.vertexUV(xf + 1.0f, y1f - 0.2f, zf + 0.5f - 0.5f, texU_2, texV_1); t.vertexUV(xf + 1.0f, y1f + 0.0f, zf + 0.5f + 0.5f, texU_2, texV_2); t.vertexUV(xf + 0.0f, y1f + 0.0f, zf + 0.5f + 0.5f, texU_1, texV_2); t.vertexUV(xf + 0.0f, y1f - 0.2f, zf + 0.5f - 0.5f, texU_1, texV_1); } else { float y1f = float(y + 1); t.vertexUV(xf + 0.0f, y1f - 0.2f, zf + 0.0f, texU_2, texV_1); t.vertexUV(xf + 1.0f, y1f + 0.0f, zf + 0.0f, texU_2, texV_2); t.vertexUV(xf + 1.0f, y1f + 0.0f, zf + 1.0f, texU_1, texV_2); t.vertexUV(xf + 0.0f, y1f - 0.2f, zf + 1.0f, texU_1, texV_1); t.vertexUV(xf + 1.0f, y1f - 0.2f, zf + 1.0f, texU_2, texV_1); t.vertexUV(xf + 0.0f, y1f + 0.0f, zf + 1.0f, texU_2, texV_2); t.vertexUV(xf + 0.0f, y1f + 0.0f, zf + 0.0f, texU_1, texV_2); t.vertexUV(xf + 1.0f, y1f - 0.2f, zf + 0.0f, texU_1, texV_1); } } // @NOTE: Returning true when you may not necessarily have rendered something? return true; } bool TileRenderer::tesselateInWorld(Tile* tile, int x, int y, int z) { int shape = tile->getRenderShape(); tile->updateShape(m_pLevelSource, x, y, z); switch (shape) { // @NOTE: In the original Minecraft PE, if a shape is undefined, the tile is invisible. // @NOTE: In v0.1.0, fire is invisible. #ifndef ORIGINAL_CODE case SHAPE_NONE: return false; case SHAPE_FIRE: return tesselateFireInWorld(tile, x, y, z); default: #endif case SHAPE_SOLID: return tesselateBlockInWorld(tile, x, y, z); case SHAPE_WATER: return tesselateWaterInWorld(tile, x, y, z); case SHAPE_CROSS: return tesselateCrossInWorld(tile, x, y, z); case SHAPE_TORCH: return tesselateTorchInWorld(tile, x, y, z); case SHAPE_LADDER: return tesselateLadderInWorld(tile, x, y, z); case SHAPE_DOOR: return tesselateDoorInWorld(tile, x, y, z); case SHAPE_STAIRS: return tesselateStairsInWorld(tile, x, y, z); } return false; } bool TileRenderer::tesselateInWorldNoCulling(Tile* tile, int x, int y, int z) { m_bDisableCulling = true; bool r = tesselateInWorld(tile, x, y, z); m_bDisableCulling = false; return r; } bool TileRenderer::tesselateInWorld(Tile* tile, int x, int y, int z, int a) { m_textureOverride = a; bool r = tesselateInWorld(tile, x, y, z); m_textureOverride = -1; return r; } bool TileRenderer::tesselateBlockInWorldWithAmbienceOcclusion(Tile* a2, int a3, int a4, int a5, float a6, float a7, float a8) { float v12; // r0 LevelSource* v13; // r1 float v14; // r0 LevelSource* v15; // r1 float v16; // r0 LevelSource* v17; // r1 float v18; // r0 LevelSource* v19; // r1 float v20; // r0 LevelSource* v21; // r1 float v22; // r0 LevelSource* v23; // r1 char v24; // r3 LevelSource* v25; // r0 char v26; // r3 LevelSource* v27; // r0 char v28; // r3 LevelSource* v29; // r0 char v30; // r3 LevelSource* v31; // r0 char v32; // r3 LevelSource* v33; // r0 char v34; // r3 LevelSource* v35; // r0 char v36; // r3 LevelSource* v37; // r0 char v38; // r3 LevelSource* v39; // r0 char v40; // r3 LevelSource* v41; // r0 char v42; // r3 LevelSource* v43; // r0 char v44; // r3 LevelSource* v45; // r0 int v46; // r8 float v47; // r0 LevelSource* v48; // r1 float v49; // r0 LevelSource* v50; // r1 float v51; // r0 LevelSource* v52; // r1 float v53; // r0 bool v54; // r3 float v55; // s12 float v56; // s11 float v57; // s8 float v58; // s14 float v59; // s13 float v60; // s9 float v61; // s10 float v62; // s13 float v63; // s11 float v64; // s10 float v65; // s14 float v66; // s15 float v67; // s12 LevelSource* v68; // r1 int v69; // r8 int v70; // r0 float v71; // r0 LevelSource* v72; // r1 float v73; // r0 LevelSource* v74; // r1 float v75; // r0 LevelSource* v76; // r1 float v77; // r0 bool v78; // r3 float v79; // s13 float v80; // s10 float v81; // s9 float v82; // s11 float v83; // s12 float v84; // s15 float v85; // s12 float v86; // s10 float v87; // s15 float v88; // s13 float v89; // s14 LevelSource* v90; // r1 int v91; // r0 float v92; // r0 LevelSource* v93; // r1 float v94; // r0 LevelSource* v95; // r1 float v96; // r0 LevelSource* v97; // r1 float v98; // r0 bool v99; // r3 float v100; // s13 float v101; // s11 float v102; // s8 float v103; // s14 float v104; // s12 float v105; // s10 float v106; // s11 float v107; // s12 float v108; // s9 float v109; // s10 float v110; // s11 float v111; // s13 float v112; // s15 float v113; // s14 float v114; // s12 LevelSource* v115; // r1 int v116; // r0 float v117; // r0 LevelSource* v118; // r1 float v119; // r0 LevelSource* v120; // r1 float v121; // r0 LevelSource* v122; // r1 float v123; // r0 bool v124; // r3 float v125; // s15 float v126; // s11 float v127; // s8 float v128; // s12 float v129; // s13 float v130; // s9 float v131; // s10 float v132; // s13 float v133; // s11 float v134; // s10 float v135; // s15 float v136; // s14 float v137; // s12 LevelSource* v138; // r1 int v139; // r0 float v140; // r0 LevelSource* v141; // r1 float v142; // r0 LevelSource* v143; // r1 float v144; // r0 LevelSource* v145; // r1 float v146; // r0 bool v147; // r3 float v148; // s12 float v149; // s9 float v150; // s11 float v151; // s14 float v152; // s10 float v153; // s13 float v154; // s9 float v155; // s12 float v156; // s13 float v157; // s9 float v158; // s10 float v159; // s11 float v160; // s15 float v161; // s14 float v162; // s12 LevelSource* v163; // r1 int v164; // r0 float v165; // r0 LevelSource* v166; // r1 float v167; // r0 LevelSource* v168; // r1 float v169; // r0 LevelSource* v170; // r1 float v171; // r0 bool v172; // r3 float v173; // r0 bool v174; // r3 float v175; // r0 bool v176; // r3 float v177; // r0 float v178; // s15 float v179; // s13 float v180; // s10 float v181; // s12 float v182; // s9 float v183; // s11 float v184; // s13 float v185; // s15 float v186; // s13 float v187; // s11 float v188; // s10 float v189; // s14 float v190; // s15 float v191; // s12 LevelSource* v192; // r1 int v193; // r0 int result; // r0 bool v195; // r3 bool v196; // r3 float v197; // r0 bool v198; // r3 float v199; // r0 bool v200; // r3 float v201; // r0 bool v202; // r3 float v203; // r0 float v204; // r0 bool v205; // r3 float v206; // r0 float v207; // r0 float v208; // r0 bool v209; // r3 float v210; // r0 float v211; // r0 bool v212; // r3 float v213; // r0 int v214; // [sp+Ch] [bp-5Ch] int v215; // [sp+10h] [bp-58h] int v216; // [sp+14h] [bp-54h] int v217; // [sp+18h] [bp-50h] int v218; // [sp+1Ch] [bp-4Ch] int v219; // [sp+20h] [bp-48h] int v220; // [sp+24h] [bp-44h] int v221; // [sp+28h] [bp-40h] int v222; // [sp+2Ch] [bp-3Ch] this->m_bAmbientOcclusion = 1; v12 = a2->getBrightness(this->m_pLevelSource, a3, a4, a5); v13 = this->m_pLevelSource; this->field_C = v12; v14 = a2->getBrightness(v13, a3 - 1, a4, a5); v218 = a4 - 1; v15 = this->m_pLevelSource; this->field_10 = v14; v16 = a2->getBrightness(v15, a3, a4 - 1, a5); v217 = a5 - 1; v17 = this->m_pLevelSource; this->field_14 = v16; v18 = a2->getBrightness(v17, a3, a4, a5 - 1); v214 = a3 + 1; v19 = this->m_pLevelSource; this->field_18 = v18; v20 = a2->getBrightness(v19, a3 + 1, a4, a5); v216 = a4 + 1; v21 = this->m_pLevelSource; this->field_1C = v20; v22 = a2->getBrightness(v21, a3, a4 + 1, a5); v215 = a5 + 1; v23 = this->m_pLevelSource; this->field_20 = v22; this->field_24 = a2->getBrightness(v23, a3, a4, a5 + 1); v24 = Tile::translucent[this->m_pLevelSource->getTile(a3 + 1, a4 + 1, a5)]; v25 = this->m_pLevelSource; this->field_AD = v24; v26 = Tile::translucent[v25->getTile(a3 + 1, a4 - 1, a5)]; v27 = this->m_pLevelSource; this->field_B5 = v26; v28 = Tile::translucent[v27->getTile(a3 + 1, a4, a5 + 1)]; v29 = this->m_pLevelSource; this->field_B1 = v28; v30 = Tile::translucent[v29->getTile(a3 + 1, a4, a5 - 1)]; v31 = this->m_pLevelSource; this->field_B3 = v30; v32 = Tile::translucent[v31->getTile(a3 - 1, a4 + 1, a5)]; v33 = this->m_pLevelSource; this->field_AE = v32; v34 = Tile::translucent[v33->getTile(a3 - 1, a4 - 1, a5)]; v35 = this->m_pLevelSource; this->field_B6 = v34; v36 = Tile::translucent[v35->getTile(a3 - 1, a4, a5 - 1)]; v37 = this->m_pLevelSource; this->field_B0 = v36; v38 = Tile::translucent[v37->getTile(a3 - 1, a4, a5 + 1)]; v39 = this->m_pLevelSource; this->field_B2 = v38; v40 = Tile::translucent[v39->getTile(a3, a4 + 1, a5 + 1)]; v41 = this->m_pLevelSource; this->field_AF = v40; v42 = Tile::translucent[v41->getTile(a3, a4 + 1, a5 - 1)]; v43 = this->m_pLevelSource; this->field_AC = v42; v44 = Tile::translucent[v43->getTile(a3, a4 - 1, a5 + 1)]; v45 = this->m_pLevelSource; this->field_B7 = v44; this->field_B4 = Tile::translucent[v45->getTile(a3, a4 - 1, a5 - 1)]; if (a2->m_TextureFrame == 3) { v219 = 0; v220 = 0; v46 = 0; v221 = 0; v222 = 0; } else { v46 = 1; v219 = 1; v220 = 1; v221 = 1; v222 = 1; } if (!this->m_bDisableCulling && !a2->shouldRenderFace(this->m_pLevelSource, a3, v218, a5, this->m_bDisableCulling)) { v69 = 0; goto LABEL_20; } if (this->field_78 > 0) { v47 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v218, a5); v48 = this->m_pLevelSource; this->field_2C = v47; v49 = a2->getBrightness(v48, a3, v218, v217); v50 = this->m_pLevelSource; this->field_34 = v49; v51 = a2->getBrightness(v50, a3, v218, v215); v52 = this->m_pLevelSource; this->field_38 = v51; v53 = a2->getBrightness(v52, v214, v218, a5); v54 = this->field_B4; this->field_40 = v53; if (v54 || this->field_B6) this->field_28 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v218, v217); else this->field_28 = this->field_2C; if (this->field_B7 || this->field_B6) this->field_30 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v218, v215); else this->field_30 = this->field_2C; if (this->field_B4 || this->field_B5) this->field_3C = a2->getBrightness(this->m_pLevelSource, v214, v218, v217); else this->field_3C = this->field_40; if (this->field_B7 || this->field_B5) { v203 = a2->getBrightness(this->m_pLevelSource, v214, v218, v215); v55 = this->field_40; v56 = v203; this->field_44 = v203; } else { v55 = this->field_40; v56 = v55; this->field_44 = v55; } v57 = this->field_2C; v58 = this->field_14; v59 = this->field_38; v60 = (float)((float)((float)(v57 + this->field_30) + v59) + v58) * 0.25f; v61 = this->field_34; v62 = (float)((float)(v56 + (float)(v59 + v58)) + v55) * 0.25f; v63 = (float)((float)(v55 + (float)(v58 + v61)) + this->field_3C) * 0.25f; v64 = (float)(v61 + (float)(v58 + (float)(v57 + this->field_28))) * 0.25f; if (v46) goto LABEL_18; LABEL_34: v66 = 0.5f; this->m_vtxRed[3] = 0.5f; this->m_vtxRed[2] = 0.5f; this->m_vtxRed[1] = 0.5f; this->m_vtxRed[0] = 0.5f; this->m_vtxGreen[3] = 0.5f; this->m_vtxGreen[2] = 0.5f; this->m_vtxGreen[1] = 0.5f; this->m_vtxGreen[0] = 0.5f; v65 = 0.5f; v67 = 0.5f; goto LABEL_19; } v62 = this->field_14; v63 = v62; v64 = v62; v60 = v62; if (!v46) goto LABEL_34; LABEL_18: v65 = a6 * 0.5f; v66 = a7 * 0.5f; this->m_vtxRed[3] = a6 * 0.5f; this->m_vtxRed[2] = a6 * 0.5f; this->m_vtxRed[1] = a6 * 0.5f; this->m_vtxRed[0] = a6 * 0.5f; v67 = a8 * 0.5f; this->m_vtxGreen[3] = a7 * 0.5f; this->m_vtxGreen[2] = a7 * 0.5f; this->m_vtxGreen[1] = a7 * 0.5f; this->m_vtxGreen[0] = a7 * 0.5f; LABEL_19: v68 = this->m_pLevelSource; v69 = 1; this->m_vtxRed[0] = v60 * v65; this->m_vtxGreen[0] = v60 * v66; this->m_vtxBlue[0] = v60 * v67; this->m_vtxRed[1] = v64 * v65; this->m_vtxGreen[1] = v64 * v66; this->m_vtxBlue[1] = v64 * v67; this->m_vtxRed[2] = v63 * v65; this->m_vtxGreen[2] = v63 * v66; this->m_vtxGreen[3] = v62 * v66; this->m_vtxBlue[2] = v63 * v67; this->m_vtxRed[3] = v62 * v65; this->m_vtxBlue[3] = v62 * v67; v70 = a2->getTexture(v68, a3, a4, a5, 0); renderFaceUp(a2, (float)a3, (float)a4, (float)a5, v70); LABEL_20: if (this->m_bDisableCulling || a2->shouldRenderFace(this->m_pLevelSource, a3, v216, a5, 1)) { if (this->field_78 <= 0) { v87 = this->field_20; v89 = v87; v88 = v87; v85 = v87; goto LABEL_36; } v71 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v216, a5); v72 = this->m_pLevelSource; this->field_4C = v71; v73 = a2->getBrightness(v72, v214, v216, a5); v74 = this->m_pLevelSource; this->field_5C = v73; v75 = a2->getBrightness(v74, a3, v216, v217); v76 = this->m_pLevelSource; this->field_54 = v75; v77 = a2->getBrightness(v76, a3, v216, v215); v78 = this->field_AC; this->field_60 = v77; if (v78 || this->field_AE) { v197 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v216, v217); v198 = this->field_AC; this->field_48 = v197; if (v198) goto LABEL_125; } else { this->field_48 = this->field_4C; } if (!this->field_AD) { this->field_58 = this->field_5C; LABEL_27: if (this->field_AF || this->field_AE) { v211 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v216, v215); v212 = this->field_AF; this->field_50 = v211; if (v212) goto LABEL_141; } else { this->field_50 = this->field_4C; } if (!this->field_AD) { v79 = this->field_5C; v80 = v79; this->field_64 = v79; LABEL_32: v81 = this->field_4C; v82 = this->field_20; v83 = this->field_60; v84 = (float)(v81 + this->field_50) + v83; v85 = (float)((float)(v80 + (float)(v83 + v82)) + v79) * 0.25f; v86 = this->field_54; v87 = (float)(v84 + v82) * 0.25f; v88 = (float)((float)(v79 + (float)(v82 + v86)) + this->field_58) * 0.25f; v89 = (float)(v86 + (float)(v82 + (float)(v81 + this->field_48))) * 0.25f; LABEL_36: v90 = this->m_pLevelSource; v69 = 1; this->m_vtxRed[0] = v85 * a6; this->m_vtxGreen[0] = v85 * a7; this->m_vtxBlue[0] = v85 * a8; this->m_vtxRed[1] = v88 * a6; this->m_vtxGreen[1] = v88 * a7; this->m_vtxBlue[1] = v88 * a8; this->m_vtxRed[2] = v89 * a6; this->m_vtxGreen[2] = v89 * a7; this->m_vtxBlue[2] = v89 * a8; this->m_vtxRed[3] = v87 * a6; this->m_vtxGreen[3] = v87 * a7; this->m_vtxBlue[3] = v87 * a8; v91 = a2->getTexture(v90, a3, a4, a5, 1); renderFaceDown(a2, (float)a3, (float)a4, (float)a5, v91); goto LABEL_37; } LABEL_141: v213 = a2->getBrightness(this->m_pLevelSource, v214, v216, v215); v79 = this->field_5C; v80 = v213; this->field_64 = v213; goto LABEL_32; } LABEL_125: this->field_58 = a2->getBrightness(this->m_pLevelSource, v214, v216, v217); goto LABEL_27; } LABEL_37: if (!this->m_bDisableCulling && !a2->shouldRenderFace(this->m_pLevelSource, a3, a4, v217, 2)) { if (this->m_bDisableCulling) goto LABEL_54; goto LABEL_107; } if (this->field_78 <= 0) { v111 = this->field_18; v110 = v111; v109 = v111; v108 = v111; if (!v222) goto LABEL_50; goto LABEL_52; } v92 = a2->getBrightness(this->m_pLevelSource, a3 - 1, a4, v217); v93 = this->m_pLevelSource; this->field_68 = v92; v94 = a2->getBrightness(v93, a3, v218, v217); v95 = this->m_pLevelSource; this->field_34 = v94; v96 = a2->getBrightness(v95, a3, v216, v217); v97 = this->m_pLevelSource; this->field_54 = v96; v98 = a2->getBrightness(v97, v214, a4, v217); v99 = this->field_B0; this->field_6C = v98; if (v99 || this->field_B4) { v201 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v218, v217); v202 = this->field_B0; this->field_28 = v201; if (v202) goto LABEL_131; } else { this->field_28 = this->field_68; } if (this->field_AC) { LABEL_131: this->field_48 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v216, v217); goto LABEL_44; } this->field_48 = this->field_68; LABEL_44: if (this->field_B3 || this->field_B4) { v204 = a2->getBrightness(this->m_pLevelSource, v214, v218, v217); v205 = this->field_B3; this->field_3C = v204; if (v205) goto LABEL_136; } else { this->field_3C = this->field_6C; } if (!this->field_AC) { v100 = this->field_6C; v101 = v100; this->field_58 = v100; goto LABEL_49; } LABEL_136: v206 = a2->getBrightness(this->m_pLevelSource, v214, v216, v217); v100 = this->field_6C; v101 = v206; this->field_58 = v206; LABEL_49: v102 = this->field_68; v103 = this->field_18; v104 = this->field_54; v105 = (float)((float)(v102 + this->field_48) + v103) + v104; v106 = v101 + (float)((float)(v103 + v104) + v100); v107 = this->field_34; v108 = v105 * 0.25f; v109 = v106 * 0.25f; v110 = (float)(v100 + (float)((float)(v103 + v107) + this->field_3C)) * 0.25f; v111 = (float)(v103 + (float)(v107 + (float)(v102 + this->field_28))) * 0.25f; if (!v222) { LABEL_50: v112 = 0.8f; this->m_vtxRed[3] = 0.8f; this->m_vtxRed[2] = 0.8f; this->m_vtxRed[1] = 0.8f; this->m_vtxRed[0] = 0.8f; this->m_vtxGreen[3] = 0.8f; this->m_vtxGreen[2] = 0.8f; this->m_vtxGreen[1] = 0.8f; this->m_vtxGreen[0] = 0.8f; v113 = 0.8f; v114 = 0.8f; goto LABEL_53; } LABEL_52: v113 = a6 * 0.8f; v112 = a7 * 0.8f; this->m_vtxRed[3] = a6 * 0.8f; this->m_vtxRed[2] = a6 * 0.8f; this->m_vtxRed[1] = a6 * 0.8f; this->m_vtxRed[0] = a6 * 0.8f; v114 = a8 * 0.8f; this->m_vtxGreen[3] = a7 * 0.8f; this->m_vtxGreen[2] = a7 * 0.8f; this->m_vtxGreen[1] = a7 * 0.8f; this->m_vtxGreen[0] = a7 * 0.8f; LABEL_53: v115 = this->m_pLevelSource; v69 = 1; this->m_vtxRed[0] = v108 * v113; this->m_vtxGreen[0] = v108 * v112; this->m_vtxBlue[0] = v108 * v114; this->m_vtxRed[1] = v109 * v113; this->m_vtxGreen[1] = v109 * v112; this->m_vtxBlue[1] = v109 * v114; this->m_vtxRed[2] = v110 * v113; this->m_vtxGreen[2] = v110 * v112; this->m_vtxGreen[3] = v111 * v112; this->m_vtxBlue[2] = v110 * v114; this->m_vtxRed[3] = v111 * v113; this->m_vtxBlue[3] = v111 * v114; v116 = a2->getTexture(v115, a3, a4, a5, 2); renderNorth(a2, (float)a3, (float)a4, (float)a5, v116); if (this->m_bDisableCulling) goto LABEL_54; LABEL_107: if (!a2->shouldRenderFace(this->m_pLevelSource, a3, a4, v215, 3)) { if (this->m_bDisableCulling) goto LABEL_70; goto LABEL_109; } LABEL_54: if (this->field_78 <= 0) { v132 = this->field_24; v133 = v132; v134 = v132; v130 = v132; if (!v221) goto LABEL_66; goto LABEL_68; } v117 = a2->getBrightness(this->m_pLevelSource, a3 - 1, a4, v215); v118 = this->m_pLevelSource; this->field_70 = v117; v119 = a2->getBrightness(v118, v214, a4, v215); v120 = this->m_pLevelSource; this->field_74 = v119; v121 = a2->getBrightness(v120, a3, v218, v215); v122 = this->m_pLevelSource; this->field_38 = v121; v123 = a2->getBrightness(v122, a3, v216, v215); v124 = this->field_B2; this->field_60 = v123; if (v124 || this->field_B7) { v199 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v218, v215); v200 = this->field_B2; this->field_30 = v199; if (v200) goto LABEL_129; } else { this->field_30 = this->field_70; } if (this->field_AF) { LABEL_129: this->field_50 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v216, v215); goto LABEL_60; } this->field_50 = this->field_70; LABEL_60: if (this->field_B1 || this->field_B7) { v208 = a2->getBrightness(this->m_pLevelSource, v214, v218, v215); v209 = this->field_B1; this->field_44 = v208; if (v209) goto LABEL_139; } else { this->field_44 = this->field_74; } if (!this->field_AF) { v125 = this->field_74; v126 = v125; this->field_64 = v125; goto LABEL_65; } LABEL_139: v210 = a2->getBrightness(this->m_pLevelSource, v214, v216, v215); v125 = this->field_74; v126 = v210; this->field_64 = v210; LABEL_65: v127 = this->field_70; v128 = this->field_24; v129 = this->field_60; v130 = (float)((float)((float)(v127 + this->field_50) + v128) + v129) * 0.25f; v131 = this->field_38; v132 = (float)(v126 + (float)((float)(v128 + v129) + v125)) * 0.25f; v133 = (float)(v125 + (float)((float)(v128 + v131) + this->field_44)) * 0.25f; v134 = (float)(v128 + (float)(v131 + (float)(v127 + this->field_30))) * 0.25f; if (!v221) { LABEL_66: v135 = 0.8f; this->m_vtxRed[3] = 0.8f; this->m_vtxRed[2] = 0.8f; this->m_vtxRed[1] = 0.8f; this->m_vtxRed[0] = 0.8f; this->m_vtxGreen[3] = 0.8f; this->m_vtxGreen[2] = 0.8f; this->m_vtxGreen[1] = 0.8f; this->m_vtxGreen[0] = 0.8f; v136 = 0.8f; v137 = 0.8f; goto LABEL_69; } LABEL_68: v136 = a6 * 0.8f; v135 = a7 * 0.8f; this->m_vtxRed[3] = a6 * 0.8f; this->m_vtxRed[2] = a6 * 0.8f; this->m_vtxRed[1] = a6 * 0.8f; this->m_vtxRed[0] = a6 * 0.8f; v137 = a8 * 0.8f; this->m_vtxGreen[3] = a7 * 0.8f; this->m_vtxGreen[2] = a7 * 0.8f; this->m_vtxGreen[1] = a7 * 0.8f; this->m_vtxGreen[0] = a7 * 0.8f; LABEL_69: v138 = this->m_pLevelSource; v69 = 1; this->m_vtxRed[0] = v130 * v136; this->m_vtxGreen[0] = v130 * v135; this->m_vtxBlue[0] = v130 * v137; this->m_vtxRed[1] = v134 * v136; this->m_vtxGreen[1] = v134 * v135; this->m_vtxBlue[1] = v134 * v137; this->m_vtxRed[2] = v133 * v136; this->m_vtxGreen[2] = v133 * v135; this->m_vtxGreen[3] = v132 * v135; this->m_vtxBlue[2] = v133 * v137; this->m_vtxRed[3] = v132 * v136; this->m_vtxBlue[3] = v132 * v137; v139 = a2->getTexture(v138, a3, a4, a5, 3); renderSouth(a2, (float)a3, (float)a4, (float)a5, v139); if (this->m_bDisableCulling) goto LABEL_70; LABEL_109: if (!a2->shouldRenderFace(this->m_pLevelSource, a3 - 1, a4, a5, 4)) { if (this->m_bDisableCulling) goto LABEL_88; goto LABEL_111; } LABEL_70: if (this->field_78 <= 0) { v156 = this->field_10; v159 = v156; v158 = v156; v157 = v156; if (!v220) { LABEL_84: v160 = 0.6f; this->m_vtxRed[3] = 0.6f; this->m_vtxRed[2] = 0.6f; this->m_vtxRed[1] = 0.6f; this->m_vtxRed[0] = 0.6f; this->m_vtxGreen[3] = 0.6f; this->m_vtxGreen[2] = 0.6f; this->m_vtxGreen[1] = 0.6f; this->m_vtxGreen[0] = 0.6f; v161 = 0.6f; v162 = 0.6f; goto LABEL_87; } } else { v140 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v218, a5); v141 = this->m_pLevelSource; this->field_2C = v140; v142 = a2->getBrightness(v141, a3 - 1, a4, v217); v143 = this->m_pLevelSource; this->field_68 = v142; v144 = a2->getBrightness(v143, a3 - 1, a4, v215); v145 = this->m_pLevelSource; this->field_70 = v144; v146 = a2->getBrightness(v145, a3 - 1, v216, a5); v147 = this->field_B0; this->field_4C = v146; if (v147 || this->field_B6) this->field_28 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v218, v217); else this->field_28 = this->field_68; if (this->field_B2 || this->field_B6) this->field_30 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v218, v215); else this->field_30 = this->field_70; if (this->field_B0 || this->field_AE) this->field_48 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v216, v217); else this->field_48 = this->field_68; if (this->field_B2 || this->field_AE) { v207 = a2->getBrightness(this->m_pLevelSource, a3 - 1, v216, v215); v148 = this->field_70; v149 = v207; this->field_50 = v207; } else { v148 = this->field_70; v149 = v148; this->field_50 = v148; } v150 = this->field_2C; v151 = this->field_10; v152 = this->field_4C; v153 = (float)((float)(v150 + this->field_30) + v151) + v148; v154 = v149 + (float)((float)(v151 + v148) + v152); v155 = this->field_68; v156 = v153 * 0.25f; v157 = v154 * 0.25f; v158 = (float)(v152 + (float)((float)(v151 + v155) + this->field_48)) * 0.25f; v159 = (float)(v151 + (float)(v155 + (float)(v150 + this->field_28))) * 0.25f; if (!v220) goto LABEL_84; } v161 = a6 * 0.6f; v160 = a7 * 0.6f; this->m_vtxRed[3] = a6 * 0.6f; this->m_vtxRed[2] = a6 * 0.6f; this->m_vtxRed[1] = a6 * 0.6f; this->m_vtxRed[0] = a6 * 0.6f; v162 = a8 * 0.6f; this->m_vtxGreen[3] = a7 * 0.6f; this->m_vtxGreen[2] = a7 * 0.6f; this->m_vtxGreen[1] = a7 * 0.6f; this->m_vtxGreen[0] = a7 * 0.6f; LABEL_87: v163 = this->m_pLevelSource; v69 = 1; this->m_vtxRed[0] = v161 * v157; this->m_vtxGreen[0] = v160 * v157; this->m_vtxBlue[0] = v162 * v157; this->m_vtxRed[1] = v161 * v158; this->m_vtxGreen[1] = v160 * v158; this->m_vtxBlue[1] = v162 * v158; this->m_vtxRed[2] = v161 * v159; this->m_vtxGreen[2] = v160 * v159; this->m_vtxGreen[3] = v160 * v156; this->m_vtxBlue[2] = v162 * v159; this->m_vtxRed[3] = v161 * v156; this->m_vtxBlue[3] = v162 * v156; v164 = a2->getTexture(v163, a3, a4, a5, 4); renderWest(a2, (float)a3, (float)a4, (float)a5, v164); if (this->m_bDisableCulling) goto LABEL_88; LABEL_111: if (!a2->shouldRenderFace(this->m_pLevelSource, v214, a4, a5, 5)) goto LABEL_102; LABEL_88: if (this->field_78 <= 0) { v186 = this->field_1C; v187 = v186; v188 = v186; v182 = v186; if (v219) goto LABEL_100; LABEL_104: v190 = 0.6f; this->m_vtxRed[3] = 0.6f; this->m_vtxRed[2] = 0.6f; this->m_vtxRed[1] = 0.6f; this->m_vtxRed[0] = 0.6f; this->m_vtxGreen[3] = 0.6f; this->m_vtxGreen[2] = 0.6f; this->m_vtxGreen[1] = 0.6f; this->m_vtxGreen[0] = 0.6f; v189 = 0.6f; v191 = 0.6f; goto LABEL_101; } v165 = a2->getBrightness(this->m_pLevelSource, v214, v218, a5); v166 = this->m_pLevelSource; this->field_40 = v165; v167 = a2->getBrightness(v166, v214, a4, v217); v168 = this->m_pLevelSource; this->field_6C = v167; v169 = a2->getBrightness(v168, v214, a4, v215); v170 = this->m_pLevelSource; this->field_74 = v169; v171 = a2->getBrightness(v170, v214, v216, a5); v172 = this->field_B5; this->field_5C = v171; if (v172 || this->field_B3) { v173 = a2->getBrightness(this->m_pLevelSource, v214, v218, v217); v174 = this->field_B5; this->field_3C = v173; if (v174 || this->field_B1) goto LABEL_93; LABEL_121: this->field_44 = this->field_74; goto LABEL_94; } v196 = this->field_B1; this->field_3C = this->field_6C; if (!v196) goto LABEL_121; LABEL_93: this->field_44 = a2->getBrightness(this->m_pLevelSource, v214, v218, v215); LABEL_94: if (this->field_AD || this->field_B3) { v175 = a2->getBrightness(this->m_pLevelSource, v214, v216, v217); v176 = this->field_AD; this->field_58 = v175; if (v176 || this->field_B1) goto LABEL_98; } else { v195 = this->field_B1; this->field_58 = this->field_6C; if (v195) { LABEL_98: v177 = a2->getBrightness(this->m_pLevelSource, v214, v216, v215); v178 = this->field_74; v179 = v177; this->field_64 = v177; goto LABEL_99; } } v178 = this->field_74; v179 = v178; this->field_64 = v178; LABEL_99: v180 = this->field_40; v181 = this->field_1C; v182 = (float)((float)((float)(v180 + this->field_44) + v181) + v178) * 0.25f; v183 = this->field_5C; v184 = v179 + (float)((float)(v181 + v178) + v183); v185 = this->field_6C; v186 = v184 * 0.25f; v187 = (float)(v183 + (float)((float)(v181 + v185) + this->field_58)) * 0.25f; v188 = (float)(v181 + (float)(v185 + (float)(v180 + this->field_3C))) * 0.25f; if (!v219) goto LABEL_104; LABEL_100: v189 = a6 * 0.6f; v190 = a7 * 0.6f; this->m_vtxRed[3] = a6 * 0.6f; this->m_vtxRed[2] = a6 * 0.6f; this->m_vtxRed[1] = a6 * 0.6f; this->m_vtxRed[0] = a6 * 0.6f; v191 = a8 * 0.6f; this->m_vtxGreen[3] = a7 * 0.6f; this->m_vtxGreen[2] = a7 * 0.6f; this->m_vtxGreen[1] = a7 * 0.6f; this->m_vtxGreen[0] = a7 * 0.6f; LABEL_101: v192 = this->m_pLevelSource; v69 = 1; this->m_vtxRed[0] = v189 * v182; this->m_vtxGreen[0] = v190 * v182; this->m_vtxBlue[0] = v191 * v182; this->m_vtxRed[1] = v189 * v188; this->m_vtxGreen[1] = v190 * v188; this->m_vtxBlue[1] = v191 * v188; this->m_vtxRed[2] = v189 * v187; this->m_vtxGreen[2] = v190 * v187; this->m_vtxGreen[3] = v190 * v186; this->m_vtxBlue[2] = v191 * v187; this->m_vtxRed[3] = v189 * v186; this->m_vtxBlue[3] = v191 * v186; v193 = a2->getTexture(v192, a3, a4, a5, 5); renderEast(a2, (float)a3, (float)a4, (float)a5, v193); LABEL_102: result = v69; this->m_bAmbientOcclusion = 0; return result; } // this is very hacky #ifdef ENH_SHADE_HELD_TILES #ifdef MOD_DONT_COLOR_GRASS # define SHADE_IS_DECOLOR_GRASS_DEFINED true #else # define SHADE_IS_DECOLOR_GRASS_DEFINED false #endif #define SHADE_DEFINE float red = 1, grn = 1, blu = 1 #define SHADE_PREPARE do { \ red = bright, grn = bright, blu = bright; \ if (GetPatchManager()->IsGrassTinted()) { \ if (tile->m_ID == Tile::leaves->m_ID) \ red *= 0.35f, grn *= 0.65f, blu *= 0.25f; \ if (tile->m_ID == Tile::grass->m_ID) \ red *= 0.25f, grn *= 0.60f, blu *= 0.25f; \ } \ } while (0) #define SHADE_IF_NEEDED(col) t.color(col*red,col*grn,col*blu,1.0f) #define SHADE_FIXUP_GRASS do { \ if (tile->m_ID == Tile::grass->m_ID) \ red = bright, grn = bright, blu = bright; \ } while (0) #else #define SHADE_DEFINE 0 #define SHADE_PREPARE 0 #define SHADE_IF_NEEDED(col) 0 #define SHADE_FIXUP_GRASS(col) 0 #endif void TileRenderer::renderTile(Tile* tile, int data RENDER_TILE_ARG_PATCH) { Tesselator& t = Tesselator::instance; #ifdef ENH_SHADE_HELD_TILES t.color(bright, bright, bright); #else t.color(255, 255, 255); #endif int shape = tile->getRenderShape(); if (shape == SHAPE_SOLID) { glTranslatef(-0.5f, -0.5f, -0.5f); t.begin(); SHADE_DEFINE; SHADE_PREPARE; SHADE_IF_NEEDED(1.0f); renderFaceDown(tile, 0.0f, 0.0f, 0.0f, tile->getTexture(DIR_YPOS, data)); SHADE_FIXUP_GRASS; SHADE_IF_NEEDED(0.5f); renderFaceUp (tile, 0.0f, 0.0f, 0.0f, tile->getTexture(DIR_YNEG, data)); SHADE_IF_NEEDED(0.8f); renderNorth (tile, 0.0f, 0.0f, 0.0f, tile->getTexture(DIR_ZNEG, data)); renderSouth (tile, 0.0f, 0.0f, 0.0f, tile->getTexture(DIR_ZPOS, data)); SHADE_IF_NEEDED(0.6f); renderWest (tile, 0.0f, 0.0f, 0.0f, tile->getTexture(DIR_XNEG, data)); renderEast (tile, 0.0f, 0.0f, 0.0f, tile->getTexture(DIR_XPOS, data)); SHADE_IF_NEEDED(1.0f); t.draw(); glTranslatef(0.5f, 0.5f, 0.5f); return; } if (shape == SHAPE_CROSS) { // unused t.begin(); tesselateCrossTexture(tile, data, -0.5f, -0.5f, -0.5f); t.draw(); return; } if (shape == SHAPE_STAIRS) { // Fixed version from 0.1.1j+ t.addOffset(-0.5f, -0.5f, -0.5f); for (int i = 0; i < 2; i++) { if (!i) tile->setShape(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f); else tile->setShape(0.0f, 0.0f, 0.5f, 1.0f, 0.5f, 1.0f); t.begin(); SHADE_DEFINE; SHADE_PREPARE; SHADE_IF_NEEDED(0.5f); renderFaceUp (tile, 0.0f, 0.0f, 0.0f, tile->getTexture(DIR_YNEG, data)); SHADE_IF_NEEDED(1.0f); renderFaceDown(tile, 0.0f, 0.0f, 0.0f, tile->getTexture(DIR_YPOS, data)); SHADE_IF_NEEDED(0.6f); renderNorth (tile, 0.0f, 0.0f, 0.0f, tile->getTexture(DIR_ZNEG, data)); renderSouth (tile, 0.0f, 0.0f, 0.0f, tile->getTexture(DIR_ZPOS, data)); SHADE_IF_NEEDED(0.8f); renderWest (tile, 0.0f, 0.0f, 0.0f, tile->getTexture(DIR_XNEG, data)); renderEast (tile, 0.0f, 0.0f, 0.0f, tile->getTexture(DIR_XPOS, data)); SHADE_IF_NEEDED(1.0f); t.draw(); } t.addOffset(0.5f, 0.5f, 0.5f); return; } } #ifdef ENH_USE_OWN_AO bool TileRenderer::tesselateBlockInWorldWithAmbienceOcclusionV2(Tile* tile, int x, int y, int z, float r, float g, float b) { // START OF AUXILIARY DATA FOR AO // Well, this is a big enum. enum eDirection { EDIR_HERE, // Here (no change in coordinates) EDIR_N, // -Z EDIR_S, // +Z EDIR_W, // -X EDIR_E, // +X EDIR_NW, // -X-Z EDIR_NE, // +X-Z EDIR_SW, // -X+Z EDIR_SE, // +X+Z EDIR_U, // +Y EDIR_UN, // +Y-Z EDIR_US, // +Y+Z EDIR_UW, // +Y-X EDIR_UE, // +Y+X EDIR_UNW,// +Y-X-Z EDIR_UNE,// +Y+X-Z EDIR_USW,// +Y-X+Z EDIR_USE,// +Y+X+Z EDIR_D, // -Y EDIR_DN, // -Y-Z EDIR_DS, // -Y+Z EDIR_DW, // -Y-X EDIR_DE, // -Y+X EDIR_DNW,// -Y-X-Z EDIR_DNE,// -Y+X-Z EDIR_DSW,// -Y-X+Z EDIR_DSE,// -Y+X+Z EDIR_COUNT, }; // for DIR_? directions static const int diffX[] = { 0,0,0,0,-1,1 }; static const int diffZ[] = { 0,0,-1,1,0,0 }; static const int diffY[] = { -1,1,0,0,0,0 }; // for EDIR_? directions static const int diffEX[] = { 0,0,0,-1,+1,-1,+1,-1,+1,0,0,0,-1,+1,-1,+1,-1,+1,0,0,0,-1,+1,-1,+1,-1,+1 }; static const int diffEZ[] = { 0,-1,+1,0,0,-1,-1,+1,+1,0,-1,+1,0,0,-1,-1,+1,+1,0,-1,+1,0,0,-1,-1,+1,+1 }; static const int diffEY[] = { 0,0,0,0,0,0,0,0,0, +1,+1,+1,+1,+1,+1,+1,+1,+1, -1,-1,-1,-1,-1,-1,-1,-1,-1 }; // Convert a DIR_? to an EDIR_? static const int dirToEdir[] = { EDIR_D, EDIR_U, EDIR_N, EDIR_S, EDIR_W, EDIR_E }; // this is a huge table. Essentially this tells us which 3 tiles we should base our lighting value on aside from the // one that's pointed to by the face we're rendering. // The array is 6 * 4 * 3. 6 for the directions, 4 for the number of vertices per face, and 3 for the number of other tiles we'll check. static const int massLUT[] = { EDIR_DS, EDIR_DW, EDIR_DSW, EDIR_DN, EDIR_DW, EDIR_DNW, EDIR_DN, EDIR_DE, EDIR_DNE, EDIR_DS, EDIR_DE, EDIR_DSE, EDIR_US, EDIR_UE, EDIR_USE, EDIR_UN, EDIR_UE, EDIR_UNE, EDIR_UN, EDIR_UW, EDIR_UNW, EDIR_US, EDIR_UW, EDIR_USW, EDIR_UN, EDIR_NW, EDIR_UNW, EDIR_UN, EDIR_NE, EDIR_UNE, EDIR_DN, EDIR_NE, EDIR_DNE, EDIR_DN, EDIR_NW, EDIR_DNW, EDIR_US, EDIR_SW, EDIR_USW, EDIR_DS, EDIR_SW, EDIR_DSW, EDIR_DS, EDIR_SE, EDIR_DSE, EDIR_US, EDIR_SE, EDIR_USE, EDIR_UW, EDIR_SW, EDIR_USW, EDIR_UW, EDIR_NW, EDIR_UNW, EDIR_DW, EDIR_NW, EDIR_DNW, EDIR_DW, EDIR_SW, EDIR_DSW, EDIR_DE, EDIR_SE, EDIR_DSE, EDIR_DE, EDIR_NE, EDIR_DNE, EDIR_UE, EDIR_NE, EDIR_UNE, EDIR_UE, EDIR_SE, EDIR_USE, }; // Depending on the face, add a multiplier to our lighting value. This is the same as in regular block rendering without AO. static const float lightingMult[] = { 0.5f, 1.0f, 0.8f, 0.8f, 0.6f, 0.6f }; // END OF AUXILIARY DATA FOR AO bool bBother = false; // Check if we should bother at all. Most of the time, we don't. There are some calculations that we shouldn't do unless necessary for (int dir = DIR_YNEG; dir <= DIR_XPOS; dir++) { int tileX = x + diffX[dir], tileY = y + diffY[dir], tileZ = z + diffZ[dir]; if (!m_bDisableCulling && !tile->shouldRenderFace(m_pLevelSource, tileX, tileY, tileZ, dir)) continue; bBother = true; break; } if (!bBother) return false; float topR = r, topG = g, topB = b; if (tile == Tile::grass) r = g = b = 1.0f; //Tesselator& t = Tesselator::instance; //float fLightHere = tile->getBrightness(m_pLevelSource, x, y, z); float lights[EDIR_COUNT]; // Get the brightness of the tile we're processing, as well as all tiles around it lights[EDIR_HERE] = tile->getBrightness(m_pLevelSource, x, y, z); for (int i = 1; i < EDIR_COUNT; i++) { lights[i] = tile->getBrightness(m_pLevelSource, x + diffEX[i], y + diffEY[i], z + diffEZ[i]); } // Render all the faces. for (int dir = DIR_YNEG; dir <= DIR_XPOS; dir++) { int tileX = x + diffX[dir], tileY = y + diffY[dir], tileZ = z + diffZ[dir]; // check if we should bother in the first place if (!m_bDisableCulling && !tile->shouldRenderFace(m_pLevelSource, tileX, tileY, tileZ, dir)) { continue; } float fR = r, fG = g, fB = b; if (dir == DIR_YPOS) fR = topR, fG = topG, fB = topB; for (int i = 0; i < 4; i++) m_vtxRed[i] = m_vtxGreen[i] = m_vtxBlue[i] = 1.0f; const int* table = &massLUT[dir * 12]; for (int i = 0; i < 4; i++) { // average: the light at the tile the face's normal would point towards, and 3 other tiles // chosen based on the vertex corner number float br = lights[dirToEdir[dir]]; for (int j = 0; j < 3; j++) br += lights[table[j + i * 3]]; br *= 0.25f; m_vtxRed[i] = br; m_vtxGreen[i] = br; m_vtxBlue[i] = br; } for (int i = 0; i < 4; i++) { m_vtxRed [i] *= fR * lightingMult[dir]; m_vtxGreen[i] *= fG * lightingMult[dir]; m_vtxBlue [i] *= fB * lightingMult[dir]; } m_bAmbientOcclusion = true; switch (dir) { case DIR_YNEG: renderFaceUp (tile, float(x), float(y), float(z), tile->getTexture(m_pLevelSource, x, y, z, DIR_YNEG)); break; case DIR_YPOS: renderFaceDown(tile, float(x), float(y), float(z), tile->getTexture(m_pLevelSource, x, y, z, DIR_YPOS)); break; case DIR_ZNEG: renderNorth (tile, float(x), float(y), float(z), tile->getTexture(m_pLevelSource, x, y, z, DIR_ZNEG)); break; case DIR_ZPOS: renderSouth (tile, float(x), float(y), float(z), tile->getTexture(m_pLevelSource, x, y, z, DIR_ZPOS)); break; case DIR_XNEG: renderWest (tile, float(x), float(y), float(z), tile->getTexture(m_pLevelSource, x, y, z, DIR_XNEG)); break; case DIR_XPOS: renderEast (tile, float(x), float(y), float(z), tile->getTexture(m_pLevelSource, x, y, z, DIR_XPOS)); break; } if (TileRenderer::m_bFancyGrass && tile->getTexture(m_pLevelSource, x, y, z, dir) == TEXTURE_GRASS_SIDE && (dir == DIR_XNEG || dir == DIR_XPOS || dir == DIR_ZNEG || dir == DIR_ZPOS)) { for (int i = 0; i < 4; i++) m_vtxRed[i] = m_vtxGreen[i] = m_vtxBlue[i] = 1.0f; for (int i = 0; i < 4; i++) { // average: the light at the tile the face's normal would point towards, and 3 other tiles // chosen based on the vertex corner number float br = lights[dirToEdir[dir]]; for (int j = 0; j < 3; j++) br += lights[table[j + i * 3]]; br *= 0.25f; m_vtxRed[i] = br; m_vtxGreen[i] = br; m_vtxBlue[i] = br; } for (int i = 0; i < 4; i++) { m_vtxRed[i] *= topR * lightingMult[dir]; m_vtxGreen[i] *= topG * lightingMult[dir]; m_vtxBlue[i] *= topB * lightingMult[dir]; } switch (dir) { case DIR_YNEG: renderFaceUp(tile, float(x), float(y), float(z), TEXTURE_NONE38); break; case DIR_YPOS: renderFaceDown(tile, float(x), float(y), float(z), TEXTURE_NONE38); break; case DIR_ZNEG: renderNorth(tile, float(x), float(y), float(z), TEXTURE_NONE38); break; case DIR_ZPOS: renderSouth(tile, float(x), float(y), float(z), TEXTURE_NONE38); break; case DIR_XNEG: renderWest(tile, float(x), float(y), float(z), TEXTURE_NONE38); break; case DIR_XPOS: renderEast(tile, float(x), float(y), float(z), TEXTURE_NONE38); break; } } m_bAmbientOcclusion = false; } return true; } #endif int TileRenderer::getTileColor(Tile* tile, int x, int y, int z) { if (tile == nullptr) { return 0xffffff; } if (tile == Tile::grass && GrassColor::isAvailable() && m_bBiomeColors) { m_pLevelSource->getBiomeSource()->getBiomeBlock(x, z, 1, 1); return GrassColor::get(m_pLevelSource->getBiomeSource()->field_4[0], m_pLevelSource->getBiomeSource()->field_8[0]); } if (tile == Tile::leaves && FoliageColor::isAvailable() && m_bBiomeColors) { int data = m_pLevelSource->getData(x, y, z); if ((data & 1) == 1) { return FoliageColor::getEvergreenColor(); } if ((data & 2) == 2) { return FoliageColor::getBirchColor(); } m_pLevelSource->getBiomeSource()->getBiomeBlock(x, z, 1, 1); return FoliageColor::get(m_pLevelSource->getBiomeSource()->field_4[0], m_pLevelSource->getBiomeSource()->field_8[0]); } return tile->getColor(m_pLevelSource, x, y, z); }