#include "TileRenderer.h" #include "../Minecraft.h" #include "Tesselator.h" #include "../../world/level/LevelSource.h" #include "../../world/level/tile/Tile.h" #include "../../world/level/tile/DoorTile.h" #include "../../world/level/tile/LiquidTile.h" #include "../../world/level/tile/FenceTile.h" #include "../../world/level/tile/FenceGateTile.h" #include "../../world/level/tile/ThinFenceTile.h" #include "../../world/level/tile/BedTile.h" #include "../../world/level/tile/StemTile.h" #include "../../world/level/tile/StairTile.h" #include "../../world/Direction.h" #include "../../world/Facing.h" #include "tileentity/TileEntityRenderer.h" #include "EntityTileRenderer.h" TileRenderer::TileRenderer( LevelSource* level /* = NULL */ ) : level(level), fixedTexture(-1), xFlipTexture(false), noCulling(false), blsmooth(1), applyAmbienceOcclusion(false) { } bool TileRenderer::tesselateBlockInWorld(Tile* tt, int x, int y, int z) { int col = tt->getColor(level, x, y, z); float r = ((col >> 16) & 0xff) / 255.0f; float g = ((col >> 8) & 0xff) / 255.0f; float b = ((col) & 0xff) / 255.0f; // xFlipTexture = (x & 1) != (y & 1); if (Minecraft::useAmbientOcclusion) { return tesselateBlockInWorldWithAmbienceOcclusion(tt, x, y, z, r, g, b); } else { return tesselateBlockInWorld(tt, x, y, z, r, g, b); } } bool TileRenderer::tesselateBlockInWorld( Tile* tt, int x, int y, int z, float r, float g, float b ) { applyAmbienceOcclusion = false; float xf = (float)x; float yf = (float)y; float zf = (float)z; Tesselator& t = Tesselator::instance; bool changed = false; float c10 = 0.5f; float c11 = 1; float c2 = 0.8f; float c3 = 0.6f; float r11 = c11 * r; float g11 = c11 * g; float b11 = c11 * b; if (tt == (Tile*)Tile::grass) { r = g = b = 1.0f; } float r10 = c10 * r; float r2 = c2 * r; float r3 = c3 * r; float g10 = c10 * g; float g2 = c2 * g; float g3 = c3 * g; float b10 = c10 * b; float b2 = c2 * b; float b3 = c3 * b; float centerBrightness = tt->getBrightness(level, x, y, z); if (noCulling || tt->shouldRenderFace(level, x, y - 1, z, Facing::DOWN)) { float br = tt->getBrightness(level, x, y - 1, z); t.color(r10 * br, g10 * br, b10 * br); renderFaceDown(tt, xf, yf, zf, tt->getTexture(level, x, y, z, 0)); changed = true; } if (noCulling || tt->shouldRenderFace(level, x, y + 1, z, Facing::UP)) { float br = tt->getBrightness(level, x, y + 1, z); if (tt->yy1 != 1 && !tt->material->isLiquid()) br = centerBrightness; t.color(r11 * br, g11 * br, b11 * br); renderFaceUp(tt, xf, yf, zf, tt->getTexture(level, x, y, z, 1)); changed = true; } if (noCulling || tt->shouldRenderFace(level, x, y, z - 1, Facing::NORTH)) { float br = tt->getBrightness(level, x, y, z - 1); if (tt->zz0 > 0) br = centerBrightness; t.color(r2 * br, g2 * br, b2 * br); renderNorth(tt, xf, yf, zf, tt->getTexture(level, x, y, z, 2)); changed = true; } if (noCulling || tt->shouldRenderFace(level, x, y, z + 1, Facing::SOUTH)) { float br = tt->getBrightness(level, x, y, z + 1); if (tt->zz1 < 1) br = centerBrightness; t.color(r2 * br, g2 * br, b2 * br); renderSouth(tt, xf, yf, zf, tt->getTexture(level, x, y, z, 3)); changed = true; } if (noCulling || tt->shouldRenderFace(level, x - 1, y, z, Facing::WEST)) { float br = tt->getBrightness(level, x - 1, y, z); if (tt->xx0 > 0) br = centerBrightness; t.color(r3 * br, g3 * br, b3 * br); renderWest(tt, xf, yf, zf, tt->getTexture(level, x, y, z, 4)); changed = true; } if (noCulling || tt->shouldRenderFace(level, x + 1, y, z, Facing::EAST)) { float br = tt->getBrightness(level, x + 1, y, z); if (tt->xx1 < 1) br = centerBrightness; t.color(r3 * br, g3 * br, b3 * br); renderEast(tt, xf, yf, zf, tt->getTexture(level, x, y, z, 5)); changed = true; } return changed; } void TileRenderer::tesselateInWorld( Tile* tile, int x, int y, int z, int fixedTexture ) { this->fixedTexture = fixedTexture; tesselateInWorld(tile, x, y, z); this->fixedTexture = -1; } bool TileRenderer::tesselateInWorld( Tile* tt, int x, int y, int z ) { int shape = tt->getRenderShape(); tt->updateShape(level, x, y, z); if (shape == Tile::SHAPE_BLOCK) { return tesselateBlockInWorld(tt, x, y, z); } else if (shape == Tile::SHAPE_WATER) { return tesselateWaterInWorld(tt, x, y, z); } else if (shape == Tile::SHAPE_CACTUS) { return tesselateCactusInWorld(tt, x, y, z); } else if (shape == Tile::SHAPE_CROSS_TEXTURE) { return tesselateCrossInWorld(tt, x, y, z); } else if(shape == Tile::SHAPE_STEM) { return tesselateStemInWorld(tt, x, y, z); } else if (shape == Tile::SHAPE_ROWS) { return tesselateRowInWorld(tt, x, y, z); } else if (shape == Tile::SHAPE_TORCH) { return tesselateTorchInWorld(tt, x, y, z); //} else if (shape == Tile::SHAPE_FIRE) { // return tesselateFireInWorld(tt, x, y, z); //} else if (shape == Tile::SHAPE_RED_DUST) { // return tesselateDustInWorld(tt, x, y, z); } else if (shape == Tile::SHAPE_LADDER) { return tesselateLadderInWorld(tt, x, y, z); } else if (shape == Tile::SHAPE_DOOR) { return tesselateDoorInWorld(tt, x, y, z); //} else if (shape == Tile::SHAPE_RAIL) { // return tesselateRailInWorld(tt, x, y, z); } else if (shape == Tile::SHAPE_STAIRS) { return tesselateStairsInWorld((StairTile*)tt, x, y, z); } else if (shape == Tile::SHAPE_FENCE) { return tesselateFenceInWorld((FenceTile*)tt, x, y, z); } else if (shape == Tile::SHAPE_FENCE_GATE) { return tesselateFenceGateInWorld((FenceGateTile*) tt, x, y, z); //} else if (shape == Tile::SHAPE_LEVER) { // return tesselateLeverInWorld(tt, x, y, z); //} else if (shape == Tile::SHAPE_BED) { // return tesselateBedInWorld(tt, x, y, z); //} else if (shape == Tile::SHAPE_DIODE) { // return tesselateDiodeInWorld(tt, x, y, z); } else if (shape == Tile::SHAPE_IRON_FENCE) { return tesselateThinFenceInWorld((ThinFenceTile*) tt, x, y, z); } else if(shape == Tile::SHAPE_BED) { return tesselateBedInWorld(tt, x, y, z); } else { return false; } } void TileRenderer::tesselateInWorldNoCulling( Tile* tile, int x, int y, int z ) { noCulling = true; tesselateInWorld(tile, x, y, z); noCulling = false; } bool TileRenderer::tesselateTorchInWorld( Tile* tt, int x, int y, int z ) { int dir = level->getData(x, y, z); Tesselator& t = Tesselator::instance; float br = tt->getBrightness(level, x, y, z); if (Tile::lightEmission[tt->id] > 0) br = 1.0f; t.color(br, br, br); float r = 0.40f; float r2 = 0.5f - r; float h = 0.20f; if (dir == 1) { tesselateTorch(tt, (float)x - r2, (float)y + h, (float)z, -r, 0); } else if (dir == 2) { tesselateTorch(tt, (float)x + r2, (float)y + h, (float)z, +r, 0); } else if (dir == 3) { tesselateTorch(tt, (float)x, (float)y + h, (float)z - r2, 0, -r); } else if (dir == 4) { tesselateTorch(tt, (float)x, (float)y + h, (float)z + r2, 0, +r); } else { tesselateTorch(tt, (float)x, (float)y, (float)z, 0, 0); } return true; } bool TileRenderer::tesselateLadderInWorld( Tile* tt, int x, int y, int z ) { Tesselator& t = Tesselator::instance; int tex = tt->getTexture(0); if (fixedTexture >= 0) tex = fixedTexture; float br = tt->getBrightness(level, x, y, z); t.color(br, br, br); int xt = ((tex & 0xf) << 4); int yt = tex & 0xf0; float u0 = (xt) / 256.0f; float u1 = (xt + 15.99f) / 256.0f; float v0 = (yt) / 256.0f; float v1 = (yt + 15.99f) / 256.0f; int face = level->getData(x, y, z); float o = 0 / 16.0f; float r = 0.05f; if (face == 5) { t.vertexUV(x + r, y + 1 + o, z + 1 + o, u0, v0); t.vertexUV(x + r, y + 0 - o, z + 1 + o, u0, v1); t.vertexUV(x + r, y + 0 - o, z + 0 - o, u1, v1); t.vertexUV(x + r, y + 1 + o, z + 0 - o, u1, v0); } if (face == 4) { t.vertexUV(x + 1 - r, y + 0 - o, z + 1 + o, u1, v1); t.vertexUV(x + 1 - r, y + 1 + o, z + 1 + o, u1, v0); t.vertexUV(x + 1 - r, y + 1 + o, z + 0 - o, u0, v0); t.vertexUV(x + 1 - r, y + 0 - o, z + 0 - o, u0, v1); } if (face == 3) { t.vertexUV(x + 1 + o, y + 0 - o, z + r, u1, v1); t.vertexUV(x + 1 + o, y + 1 + o, z + r, u1, v0); t.vertexUV(x + 0 - o, y + 1 + o, z + r, u0, v0); t.vertexUV(x + 0 - o, y + 0 - o, z + r, u0, v1); } if (face == 2) { t.vertexUV(x + 1 + o, y + 1 + o, z + 1 - r, u0, v0); t.vertexUV(x + 1 + o, y + 0 - o, z + 1 - r, u0, v1); t.vertexUV(x + 0 - o, y + 0 - o, z + 1 - r, u1, v1); t.vertexUV(x + 0 - o, y + 1 + o, z + 1 - r, u1, v0); } return true; } bool TileRenderer::tesselateCrossInWorld( Tile* tt, int x, int y, int z ) { Tesselator& t = Tesselator::instance; float br = tt->getBrightness(level, x, y, z); int col = tt->getColor(level, x, y, z); float r = ((col >> 16) & 0xff) / 255.0f; float g = ((col >> 8) & 0xff) / 255.0f; float b = ((col) & 0xff) / 255.0f; t.color(br * r, br * g, br * b); float xt = float(x); float yt = float(y); float zt = float(z); if (tt == Tile::tallgrass) { long seed = (x * 3129871) ^ (z * 116129781l) ^ (y); seed = seed * seed * 42317861 + seed * 11; xt += ((((seed >> 16) & 0xf) / 15.0f) - 0.5f) * 0.5f; yt += ((((seed >> 20) & 0xf) / 15.0f) - 1.0f) * 0.2f; zt += ((((seed >> 24) & 0xf) / 15.0f) - 0.5f) * 0.5f; } tesselateCrossTexture(tt, level->getData(x, y, z), xt, yt, zt); return true; //return true; /*Tesselator& t = Tesselator::instance; float br = tt->getBrightness(level, x, y, z); t.color(br, br, br); tesselateCrossTexture(tt, level->getData(x, y, z), (float)x, (float)y, (float)z); return true;*/ } bool TileRenderer::tesselateStemInWorld( Tile* _tt, int x, int y, int z ) { StemTile* tt = (StemTile*) _tt; Tesselator& t = Tesselator::instance; float br = tt->getBrightness(level, x, y, z); int col = tt->getColor(level, x, y, z); float r = ((col >> 16) & 0xff) / 255.0f; float g = ((col >> 8) & 0xff) / 255.0f; float b = ((col) & 0xff) / 255.0f; t.color(br * r, br * g, br * b); tt->updateShape(level, x, y, z); int dir = tt->getConnectDir(level, x, y, z); if (dir < 0) { tesselateStemTexture(tt, level->getData(x, y, z), tt->yy1, float(x), float(y - 1 / 16.0f), float(z)); } else { tesselateStemTexture(tt, level->getData(x, y, z), 0.5f, float(x), float(y - 1 / 16.0f), float(z)); tesselateStemDirTexture(tt, level->getData(x, y, z), dir, tt->yy1, float(x), float(y - 1 / 16.0f), float(z)); } return true; } void TileRenderer::tesselateTorch( Tile* tt, float x, float y, float z, float xxa, float zza ) { Tesselator& t = Tesselator::instance; int tex = tt->getTexture(0); if (fixedTexture >= 0) tex = fixedTexture; int xt = (tex & 0xf) << 4; int yt = tex & 0xf0; float u0 = (xt) / 256.0f; float u1 = (xt + 15.99f) / 256.0f; float v0 = (yt) / 256.0f; float v1 = (yt + 15.99f) / 256.0f; float uc0 = u0 + 7 / 256.0f; float vc0 = v0 + 6 / 256.0f; float uc1 = u0 + 9 / 256.0f; float vc1 = v0 + 8 / 256.0f; x += 0.5f; z += 0.5f; float x0 = x - 0.5f; float x1 = x + 0.5f; float z0 = z - 0.5f; float z1 = z + 0.5f; float r = 1 / 16.0f; float h = 10.0f / 16.0f; t.vertexUV(x + xxa * (1 - h) - r, y + h, z + zza * (1 - h) - r, uc0, vc0); t.vertexUV(x + xxa * (1 - h) - r, y + h, z + zza * (1 - h) + r, uc0, vc1); t.vertexUV(x + xxa * (1 - h) + r, y + h, z + zza * (1 - h) + r, uc1, vc1); t.vertexUV(x + xxa * (1 - h) + r, y + h, z + zza * (1 - h) - r, uc1, vc0); t.vertexUV(x - r, y + 1, z0, u0, v0); t.vertexUV(x - r + xxa, y + 0, z0 + zza, u0, v1); t.vertexUV(x - r + xxa, y + 0, z1 + zza, u1, v1); t.vertexUV(x - r, y + 1, z1, u1, v0); t.vertexUV(x + r, y + 1, z1, u0, v0); t.vertexUV(x + xxa + r, y + 0, z1 + zza, u0, v1); t.vertexUV(x + xxa + r, y + 0, z0 + zza, u1, v1); t.vertexUV(x + r, y + 1, z0, u1, v0); t.vertexUV(x0, y + 1, z + r, u0, v0); t.vertexUV(x0 + xxa, y + 0, z + r + zza, u0, v1); t.vertexUV(x1 + xxa, y + 0, z + r + zza, u1, v1); t.vertexUV(x1, y + 1, z + r, u1, v0); t.vertexUV(x1, y + 1, z - r, u0, v0); t.vertexUV(x1 + xxa, y + 0, z - r + zza, u0, v1); t.vertexUV(x0 + xxa, y + 0, z - r + zza, u1, v1); t.vertexUV(x0, y + 1, z - r, u1, v0); } void TileRenderer::tesselateCrossTexture( Tile* tt, int data, float x, float y, float z ) { Tesselator& t = Tesselator::instance; int tex = tt->getTexture(0, data); if (fixedTexture >= 0) tex = fixedTexture; int xt = (tex & 0xf) << 4; int yt = tex & 0xf0; float u0 = (xt) / 256.0f; float u1 = (xt + 15.99f) / 256.0f; float v0 = (yt) / 256.0f; float v1 = (yt + 15.99f) / 256.0f; float x0 = x + 0.5f - 0.45f; float x1 = x + 0.5f + 0.45f; float z0 = z + 0.5f - 0.45f; float z1 = z + 0.5f + 0.45f; t.vertexUV(x0, y + 1, z0, u0, v0); t.vertexUV(x0, y + 0, z0, u0, v1); t.vertexUV(x1, y + 0, z1, u1, v1); t.vertexUV(x1, y + 1, z1, u1, v0); t.vertexUV(x1, y + 1, z1, u0, v0); t.vertexUV(x1, y + 0, z1, u0, v1); t.vertexUV(x0, y + 0, z0, u1, v1); t.vertexUV(x0, y + 1, z0, u1, v0); t.vertexUV(x0, y + 1, z1, u0, v0); t.vertexUV(x0, y + 0, z1, u0, v1); t.vertexUV(x1, y + 0, z0, u1, v1); t.vertexUV(x1, y + 1, z0, u1, v0); t.vertexUV(x1, y + 1, z0, u0, v0); t.vertexUV(x1, y + 0, z0, u0, v1); t.vertexUV(x0, y + 0, z1, u1, v1); t.vertexUV(x0, y + 1, z1, u1, v0); } void TileRenderer::tesselateStemTexture( Tile* tt, int data, float h, float x, float y, float z ) { Tesselator& t = Tesselator::instance; int tex = tt->getTexture(0, data); if(fixedTexture >= 0) tex = fixedTexture; int xt = (tex & 0xf) << 4; int yt = tex & 0xf0; float u0 = (xt) / 256.0f; float u1 = (xt + 15.99f) / 256.0f; float v0 = (yt) / 256.0f; float v1 = (yt + 15.99f * h) / 256.0f; float x0 = x + 0.5f - 0.45f; float x1 = x + 0.5f + 0.45f; float z0 = z + 0.5f - 0.45f; float z1 = z + 0.5f + 0.45f; t.vertexUV(x0, y + h, z0, u0, v0); t.vertexUV(x0, y + 0, z0, u0, v1); t.vertexUV(x1, y + 0, z1, u1, v1); t.vertexUV(x1, y + h, z1, u1, v0); t.vertexUV(x1, y + h, z1, u0, v0); t.vertexUV(x1, y + 0, z1, u0, v1); t.vertexUV(x0, y + 0, z0, u1, v1); t.vertexUV(x0, y + h, z0, u1, v0); t.vertexUV(x0, y + h, z1, u0, v0); t.vertexUV(x0, y + 0, z1, u0, v1); t.vertexUV(x1, y + 0, z0, u1, v1); t.vertexUV(x1, y + h, z0, u1, v0); t.vertexUV(x1, y + h, z0, u0, v0); t.vertexUV(x1, y + 0, z0, u0, v1); t.vertexUV(x0, y + 0, z1, u1, v1); t.vertexUV(x0, y + h, z1, u1, v0); } void TileRenderer::tesselateStemDirTexture( Tile* tt, int data, int dir, float h, float x, float y, float z ) { Tesselator& t = Tesselator::instance; int tex = tt->getTexture(0, data) + 16; if (fixedTexture >= 0) tex = fixedTexture; int xt = (tex & 0xf) << 4; int yt = tex & 0xf0; float u0 = (xt) / 256.0f; float u1 = (xt + 15.99f) / 256.0f; float v0 = (yt) / 256.0f; float v1 = (yt + 15.99f * h) / 256.0f; float x0 = x + 0.5f - 0.5f; float x1 = x + 0.5f + 0.5f; float z0 = z + 0.5f - 0.5f; float z1 = z + 0.5f + 0.5f; float xm = x + 0.5f; float zm = z + 0.5f; if ((dir + 1) / 2 % 2 == 1) { float tmp = u1; u1 = u0; u0 = tmp; } if (dir < 2) { t.vertexUV(x0, y + h, zm, u0, v0); t.vertexUV(x0, y + 0, zm, u0, v1); t.vertexUV(x1, y + 0, zm, u1, v1); t.vertexUV(x1, y + h, zm, u1, v0); t.vertexUV(x1, y + h, zm, u1, v0); t.vertexUV(x1, y + 0, zm, u1, v1); t.vertexUV(x0, y + 0, zm, u0, v1); t.vertexUV(x0, y + h, zm, u0, v0); } else { t.vertexUV(xm, y + h, z1, u0, v0); t.vertexUV(xm, y + 0, z1, u0, v1); t.vertexUV(xm, y + 0, z0, u1, v1); t.vertexUV(xm, y + h, z0, u1, v0); t.vertexUV(xm, y + h, z0, u1, v0); t.vertexUV(xm, y + 0, z0, u1, v1); t.vertexUV(xm, y + 0, z1, u0, v1); t.vertexUV(xm, y + h, z1, u0, v0); } } bool TileRenderer::tesselateWaterInWorld( Tile* tt, int x, int y, int z ) { Tesselator& t = Tesselator::instance; bool up = tt->shouldRenderFace(level, x, y + 1, z, 1); bool down = tt->shouldRenderFace(level, x, y - 1, z, 0); bool dirs[4]; // static? dirs[0] = tt->shouldRenderFace(level, x, y, z - 1, 2); dirs[1] = tt->shouldRenderFace(level, x, y, z + 1, 3); dirs[2] = tt->shouldRenderFace(level, x - 1, y, z, 4); dirs[3] = tt->shouldRenderFace(level, x + 1, y, z, 5); if (!up && !down && !dirs[0] && !dirs[1] && !dirs[2] && !dirs[3]) return false; bool changed = false; float c10 = 0.5f; float c11 = 1; float c2 = 0.8f; float c3 = 0.6f; const float yo0 = 0; const float yo1 = 1; const Material* m = tt->material; int data = level->getData(x, y, z); float h0 = getWaterHeight(x, y, z, m); float h1 = getWaterHeight(x, y, z + 1, m); float h2 = getWaterHeight(x + 1, y, z + 1, m); float h3 = getWaterHeight(x + 1, y, z, m); // renderFaceUp(tt, x, y, z, tt->getTexture(0)); if (noCulling || up) { changed = true; int tex = tt->getTexture(1, data); float angle = (float) LiquidTile::getSlopeAngle(level, x, y, z, m); if (angle > -999) { tex = tt->getTexture(2, data); } int xt = (tex & 0xf) << 4; int yt = tex & 0xf0; float uc = (xt + 0.5f * 16) / 256.0f; float vc = (yt + 0.5f * 16) / 256.0f; if (angle < -999) { angle = 0; } else { uc = (xt + 1 * 16) / 256.0f; vc = (yt + 1 * 16) / 256.0f; } float s = (Mth::sin(angle) * 8) / 256.5f; // @attn: to get rid of "jitter" (caused float c = (Mth::cos(angle) * 8) / 256.5f; // of fp rounding errors) in big oceans) float br = tt->getBrightness(level, x, y, z); t.color(c11 * br, c11 * br, c11 * br); t.vertexUV((float)x + 0, (float)y + h0, (float)z + 0, uc - c - s, vc - c + s); t.vertexUV((float)x + 0, (float)y + h1, (float)z + 1, uc - c + s, vc + c + s); t.vertexUV((float)x + 1, (float)y + h2, (float)z + 1, uc + c + s, vc + c - s); t.vertexUV((float)x + 1, (float)y + h3, (float)z + 0, uc + c - s, vc - c - s); } if (noCulling || down) { float br = tt->getBrightness(level, x, y - 1, z); t.color(c10 * br, c10 * br, c10 * br); renderFaceDown(tt, (float)x, (float)y, (float)z, tt->getTexture(0)); changed = true; } for (int face = 0; face < 4; face++) { int xt = x; int yt = y; int zt = z; if (face == 0) zt--; if (face == 1) zt++; if (face == 2) xt--; if (face == 3) xt++; int tex = tt->getTexture(face + 2, data); int xTex = (tex & 0xf) << 4; int yTex = tex & 0xf0; if (noCulling || dirs[face]) { float hh0; float hh1; float x0, z0, x1, z1; if (face == 0) { hh0 = h0; hh1 = h3; x0 = (float)(x ); x1 = (float)(x + 1); z0 = (float)(z ); z1 = (float)(z ); } else if (face == 1) { hh0 = h2; hh1 = h1; x0 = (float)(x + 1); x1 = (float)(x ); z0 = (float)(z + 1); z1 = (float)(z + 1); } else if (face == 2) { hh0 = h1; hh1 = h0; x0 = (float)(x ); x1 = (float)(x ); z0 = (float)(z + 1); z1 = (float)(z ); } else { hh0 = h3; hh1 = h2; x0 = (float)(x + 1); x1 = (float)(x + 1); z0 = (float)(z ); z1 = (float)(z + 1); } changed = true; float u0 = (xTex + 0 * 16) / 256.0f; float u1 = (xTex + 1 * 16 - 0.01f) / 256.0f; float v01 = (yTex + (1 - hh0) * 16) / 256.0f; float v02 = (yTex + (1 - hh1) * 16) / 256.0f; float v1 = (yTex + 1 * 16 - 0.01f) / 256.0f; float br = tt->getBrightness(level, xt, yt, zt); if (face < 2) br *= c2; else br *= c3; float yf = (float)y; t.color(c11 * br, c11 * br, c11 * br); t.vertexUV(x0, yf + hh0, z0, u0, v01); t.vertexUV(x1, yf + hh1, z1, u1, v02); t.vertexUV(x1, yf + 0, z1, u1, v1); t.vertexUV(x0, yf + 0, z0, u0, v1); } } //printf("w: %d ", (dirs[0] + dirs[1] + dirs[2] + dirs[3] + up + down)); tt->yy0 = yo0; tt->yy1 = yo1; return changed; } float TileRenderer::getWaterHeight( int x, int y, int z, const Material* m ) { int count = 0; float h = 0; for (int i = 0; i < 4; i++) { int xx = x - (i & 1); int yy = y; int zz = z - ((i >> 1) & 1); if (level->getMaterial(xx, yy + 1, zz) == m) { return 1; } const Material* tm = level->getMaterial(xx, yy, zz); if (tm == m) { int d = level->getData(xx, yy, zz); if (d >= 8 || d == 0) { h += (LiquidTile::getHeight(d)) * 10; count += 10; } h += LiquidTile::getHeight(d); count++; } else if (!tm->isSolid()) { h += 1; count++; } } return 1 - h / count; } void TileRenderer::renderBlock(Tile* tt, LevelSource* level, int x, int y, int z) { float c10 = 0.5f; float c11 = 1; float c2 = 0.8f; float c3 = 0.6f; Tesselator& t = Tesselator::instance; t.begin(); float center = tt->getBrightness(level, x, y, z); float br = tt->getBrightness(level, x, y - 1, z); if (br < center) br = center; t.color(c10 * br, c10 * br, c10 * br); renderFaceDown(tt, -0.5f, -0.5f, -0.5f, tt->getTexture(0)); br = tt->getBrightness(level, x, y + 1, z); if (br < center) br = center; t.color(c11 * br, c11 * br, c11 * br); renderFaceUp(tt, -0.5f, -0.5f, -0.5f, tt->getTexture(1)); br = tt->getBrightness(level, x, y, z - 1); if (br < center) br = center; t.color(c2 * br, c2 * br, c2 * br); renderNorth(tt, -0.5f, -0.5f, -0.5f, tt->getTexture(2)); br = tt->getBrightness(level, x, y, z + 1); if (br < center) br = center; t.color(c2 * br, c2 * br, c2 * br); renderSouth(tt, -0.5f, -0.5f, -0.5f, tt->getTexture(3)); br = tt->getBrightness(level, x - 1, y, z); if (br < center) br = center; t.color(c3 * br, c3 * br, c3 * br); renderWest(tt, -0.5f, -0.5f, -0.5f, tt->getTexture(4)); br = tt->getBrightness(level, x + 1, y, z); if (br < center) br = center; t.color(c3 * br, c3 * br, c3 * br); renderEast(tt, -0.5f, -0.5f, -0.5f, tt->getTexture(5)); t.draw(); } bool TileRenderer::tesselateBlockInWorldWithAmbienceOcclusion( Tile* tt, int pX, int pY, int pZ, float pBaseRed, float pBaseGreen, float pBaseBlue ) { applyAmbienceOcclusion = true; bool i = false; float ll1 = ll000; float ll2 = ll000; float ll3 = ll000; float ll4 = ll000; bool tint0 = true; bool tint1 = true; bool tint2 = true; bool tint3 = true; bool tint4 = true; bool tint5 = true; ll000 = tt->getBrightness(level, pX, pY, pZ); llx00 = tt->getBrightness(level, pX - 1, pY, pZ); ll0y0 = tt->getBrightness(level, pX, pY - 1, pZ); ll00z = tt->getBrightness(level, pX, pY, pZ - 1); llX00 = tt->getBrightness(level, pX + 1, pY, pZ); ll0Y0 = tt->getBrightness(level, pX, pY + 1, pZ); ll00Z = tt->getBrightness(level, pX, pY, pZ + 1); llTransXY0 = Tile::translucent[level->getTile(pX + 1, pY + 1, pZ)]; llTransXy0 = Tile::translucent[level->getTile(pX + 1, pY - 1, pZ)]; llTransX0Z = Tile::translucent[level->getTile(pX + 1, pY, pZ + 1)]; llTransX0z = Tile::translucent[level->getTile(pX + 1, pY, pZ - 1)]; llTransxY0 = Tile::translucent[level->getTile(pX - 1, pY + 1, pZ)]; llTransxy0 = Tile::translucent[level->getTile(pX - 1, pY - 1, pZ)]; llTransx0z = Tile::translucent[level->getTile(pX - 1, pY, pZ - 1)]; llTransx0Z = Tile::translucent[level->getTile(pX - 1, pY, pZ + 1)]; llTrans0YZ = Tile::translucent[level->getTile(pX, pY + 1, pZ + 1)]; llTrans0Yz = Tile::translucent[level->getTile(pX, pY + 1, pZ - 1)]; llTrans0yZ = Tile::translucent[level->getTile(pX, pY - 1, pZ + 1)]; llTrans0yz = Tile::translucent[level->getTile(pX, pY - 1, pZ - 1)]; if (tt->tex == 3) tint0 = tint2 = tint3 = tint4 = tint5 = false; if ((noCulling) || (tt->shouldRenderFace(level, pX, pY - 1, pZ, 0))) { if (blsmooth > 0) { pY--; llxy0 = tt->getBrightness(level, pX - 1, pY, pZ); ll0yz = tt->getBrightness(level, pX, pY, pZ - 1); ll0yZ = tt->getBrightness(level, pX, pY, pZ + 1); llXy0 = tt->getBrightness(level, pX + 1, pY, pZ); if (llTrans0yz || llTransxy0) { llxyz = tt->getBrightness(level, pX - 1, pY, pZ - 1); } else { llxyz = llxy0; } if (llTrans0yZ || llTransxy0) { llxyZ = tt->getBrightness(level, pX - 1, pY, pZ + 1); } else { llxyZ = llxy0; } if (llTrans0yz || llTransXy0) { llXyz = tt->getBrightness(level, pX + 1, pY, pZ - 1); } else { llXyz = llXy0; } if (llTrans0yZ || llTransXy0) { llXyZ = tt->getBrightness(level, pX + 1, pY, pZ + 1); } else { llXyZ = llXy0; } pY++; ll1 = (llxyZ + llxy0 + ll0yZ + ll0y0) / 4.0f; ll4 = (ll0yZ + ll0y0 + llXyZ + llXy0) / 4.0f; ll3 = (ll0y0 + ll0yz + llXy0 + llXyz) / 4.0f; ll2 = (llxy0 + llxyz + ll0y0 + ll0yz) / 4.0f; } else ll1 = ll2 = ll3 = ll4 = ll0y0; c1r = c2r = c3r = c4r = (tint0 ? pBaseRed : 1.0f) * 0.5f; c1g = c2g = c3g = c4g = (tint0 ? pBaseGreen : 1.0f) * 0.5f; c1b = c2b = c3b = c4b = (tint0 ? pBaseBlue : 1.0f) * 0.5f; c1r *= ll1; c1g *= ll1; c1b *= ll1; c2r *= ll2; c2g *= ll2; c2b *= ll2; c3r *= ll3; c3g *= ll3; c3b *= ll3; c4r *= ll4; c4g *= ll4; c4b *= ll4; renderFaceDown(tt, (float) pX, (float) pY, (float) pZ, tt->getTexture(level, pX, pY, pZ, 0)); i = true; } if ((noCulling) || (tt->shouldRenderFace(level, pX, pY + 1, pZ, 1))) { if (blsmooth > 0) { pY++; llxY0 = tt->getBrightness(level, pX - 1, pY, pZ); llXY0 = tt->getBrightness(level, pX + 1, pY, pZ); ll0Yz = tt->getBrightness(level, pX, pY, pZ - 1); ll0YZ = tt->getBrightness(level, pX, pY, pZ + 1); if (llTrans0Yz || llTransxY0) { llxYz = tt->getBrightness(level, pX - 1, pY, pZ - 1); } else { llxYz = llxY0; } if (llTrans0Yz || llTransXY0) { llXYz = tt->getBrightness(level, pX + 1, pY, pZ - 1); } else { llXYz = llXY0; } if (llTrans0YZ || llTransxY0) { llxYZ = tt->getBrightness(level, pX - 1, pY, pZ + 1); } else { llxYZ = llxY0; } if (llTrans0YZ || llTransXY0) { llXYZ = tt->getBrightness(level, pX + 1, pY, pZ + 1); } else { llXYZ = llXY0; } pY--; ll4 = (llxYZ + llxY0 + ll0YZ + ll0Y0) / 4.0f; ll1 = (ll0YZ + ll0Y0 + llXYZ + llXY0) / 4.0f; ll2 = (ll0Y0 + ll0Yz + llXY0 + llXYz) / 4.0f; ll3 = (llxY0 + llxYz + ll0Y0 + ll0Yz) / 4.0f; } else ll1 = ll2 = ll3 = ll4 = ll0Y0; c1r = c2r = c3r = c4r = (tint1 ? pBaseRed : 1.0f); c1g = c2g = c3g = c4g = (tint1 ? pBaseGreen : 1.0f); c1b = c2b = c3b = c4b = (tint1 ? pBaseBlue : 1.0f); c1r *= ll1; c1g *= ll1; c1b *= ll1; c2r *= ll2; c2g *= ll2; c2b *= ll2; c3r *= ll3; c3g *= ll3; c3b *= ll3; c4r *= ll4; c4g *= ll4; c4b *= ll4; renderFaceUp(tt, (float) pX, (float) pY, (float) pZ, tt->getTexture(level, pX, pY, pZ, 1)); i = true; } if ((noCulling) || (tt->shouldRenderFace(level, pX, pY, pZ - 1, 2))) { if (blsmooth > 0) { pZ--; llx0z = tt->getBrightness(level, pX - 1, pY, pZ); ll0yz = tt->getBrightness(level, pX, pY - 1, pZ); ll0Yz = tt->getBrightness(level, pX, pY + 1, pZ); llX0z = tt->getBrightness(level, pX + 1, pY, pZ); if (llTransx0z || llTrans0yz) { llxyz = tt->getBrightness(level, pX - 1, pY - 1, pZ); } else { llxyz = llx0z; } if (llTransx0z || llTrans0Yz) { llxYz = tt->getBrightness(level, pX - 1, pY + 1, pZ); } else { llxYz = llx0z; } if (llTransX0z || llTrans0yz) { llXyz = tt->getBrightness(level, pX + 1, pY - 1, pZ); } else { llXyz = llX0z; } if (llTransX0z || llTrans0Yz) { llXYz = tt->getBrightness(level, pX + 1, pY + 1, pZ); } else { llXYz = llX0z; } pZ++; ll1 = (llx0z + llxYz + ll00z + ll0Yz) / 4.0f; ll2 = (ll00z + ll0Yz + llX0z + llXYz) / 4.0f; ll3 = (ll0yz + ll00z + llXyz + llX0z) / 4.0f; ll4 = (llxyz + llx0z + ll0yz + ll00z) / 4.0f; } else ll1 = ll2 = ll3 = ll4 = ll00z; c1r = c2r = c3r = c4r = (tint2 ? pBaseRed : 1.0f) * 0.8f; c1g = c2g = c3g = c4g = (tint2 ? pBaseGreen : 1.0f) * 0.8f; c1b = c2b = c3b = c4b = (tint2 ? pBaseBlue : 1.0f) * 0.8f; c1r *= ll1; c1g *= ll1; c1b *= ll1; c2r *= ll2; c2g *= ll2; c2b *= ll2; c3r *= ll3; c3g *= ll3; c3b *= ll3; c4r *= ll4; c4g *= ll4; c4b *= ll4; renderNorth(tt, (float) pX, (float) pY, (float) pZ, tt->getTexture(level, pX, pY, pZ, 2)); i = true; } if ((noCulling) || (tt->shouldRenderFace(level, pX, pY, pZ + 1, 3))) { if (blsmooth > 0) { pZ++; llx0Z = tt->getBrightness(level, pX - 1, pY, pZ); llX0Z = tt->getBrightness(level, pX + 1, pY, pZ); ll0yZ = tt->getBrightness(level, pX, pY - 1, pZ); ll0YZ = tt->getBrightness(level, pX, pY + 1, pZ); if (llTransx0Z || llTrans0yZ) { llxyZ = tt->getBrightness(level, pX - 1, pY - 1, pZ); } else { llxyZ = llx0Z; } if (llTransx0Z || llTrans0YZ) { llxYZ = tt->getBrightness(level, pX - 1, pY + 1, pZ); } else { llxYZ = llx0Z; } if (llTransX0Z || llTrans0yZ) { llXyZ = tt->getBrightness(level, pX + 1, pY - 1, pZ); } else { llXyZ = llX0Z; } if (llTransX0Z || llTrans0YZ) { llXYZ = tt->getBrightness(level, pX + 1, pY + 1, pZ); } else { llXYZ = llX0Z; } pZ--; ll1 = (llx0Z + llxYZ + ll00Z + ll0YZ) / 4.0f; ll4 = (ll00Z + ll0YZ + llX0Z + llXYZ) / 4.0f; ll3 = (ll0yZ + ll00Z + llXyZ + llX0Z) / 4.0f; ll2 = (llxyZ + llx0Z + ll0yZ + ll00Z) / 4.0f; } else ll1 = ll2 = ll3 = ll4 = ll00Z; c1r = c2r = c3r = c4r = (tint3 ? pBaseRed : 1.0f) * 0.8f; c1g = c2g = c3g = c4g = (tint3 ? pBaseGreen : 1.0f) * 0.8f; c1b = c2b = c3b = c4b = (tint3 ? pBaseBlue : 1.0f) * 0.8f; c1r *= ll1; c1g *= ll1; c1b *= ll1; c2r *= ll2; c2g *= ll2; c2b *= ll2; c3r *= ll3; c3g *= ll3; c3b *= ll3; c4r *= ll4; c4g *= ll4; c4b *= ll4; renderSouth(tt, (float) pX, (float) pY, (float) pZ, tt->getTexture(level, pX, pY, pZ, 3)); i = true; } if ((noCulling) || (tt->shouldRenderFace(level, pX - 1, pY, pZ, 4))) { if (blsmooth > 0) { pX--; llxy0 = tt->getBrightness(level, pX, pY - 1, pZ); llx0z = tt->getBrightness(level, pX, pY, pZ - 1); llx0Z = tt->getBrightness(level, pX, pY, pZ + 1); llxY0 = tt->getBrightness(level, pX, pY + 1, pZ); if (llTransx0z || llTransxy0) { llxyz = tt->getBrightness(level, pX, pY - 1, pZ - 1); } else { llxyz = llx0z; } if (llTransx0Z || llTransxy0) { llxyZ = tt->getBrightness(level, pX, pY - 1, pZ + 1); } else { llxyZ = llx0Z; } if (llTransx0z || llTransxY0) { llxYz = tt->getBrightness(level, pX, pY + 1, pZ - 1); } else { llxYz = llx0z; } if (llTransx0Z || llTransxY0) { llxYZ = tt->getBrightness(level, pX, pY + 1, pZ + 1); } else { llxYZ = llx0Z; } pX++; ll4 = (llxy0 + llxyZ + llx00 + llx0Z) / 4.0f; ll1 = (llx00 + llx0Z + llxY0 + llxYZ) / 4.0f; ll2 = (llx0z + llx00 + llxYz + llxY0) / 4.0f; ll3 = (llxyz + llxy0 + llx0z + llx00) / 4.0f; } else ll1 = ll2 = ll3 = ll4 = llx00; c1r = c2r = c3r = c4r = (tint4 ? pBaseRed : 1.0f) * 0.6f; c1g = c2g = c3g = c4g = (tint4 ? pBaseGreen : 1.0f) * 0.6f; c1b = c2b = c3b = c4b = (tint4 ? pBaseBlue : 1.0f) * 0.6f; c1r *= ll1; c1g *= ll1; c1b *= ll1; c2r *= ll2; c2g *= ll2; c2b *= ll2; c3r *= ll3; c3g *= ll3; c3b *= ll3; c4r *= ll4; c4g *= ll4; c4b *= ll4; renderWest(tt, (float) pX, (float) pY, (float) pZ, tt->getTexture(level, pX, pY, pZ, 4)); i = true; } if ((noCulling) || (tt->shouldRenderFace(level, pX + 1, pY, pZ, 5))) { if (blsmooth > 0) { pX++; llXy0 = tt->getBrightness(level, pX, pY - 1, pZ); llX0z = tt->getBrightness(level, pX, pY, pZ - 1); llX0Z = tt->getBrightness(level, pX, pY, pZ + 1); llXY0 = tt->getBrightness(level, pX, pY + 1, pZ); if (llTransXy0 || llTransX0z) { llXyz = tt->getBrightness(level, pX, pY - 1, pZ - 1); } else { llXyz = llX0z; } if (llTransXy0 || llTransX0Z) { llXyZ = tt->getBrightness(level, pX, pY - 1, pZ + 1); } else { llXyZ = llX0Z; } if (llTransXY0 || llTransX0z) { llXYz = tt->getBrightness(level, pX, pY + 1, pZ - 1); } else { llXYz = llX0z; } if (llTransXY0 || llTransX0Z) { llXYZ = tt->getBrightness(level, pX, pY + 1, pZ + 1); } else { llXYZ = llX0Z; } pX--; ll1 = (llXy0 + llXyZ + llX00 + llX0Z) / 4.0f; ll4 = (llX00 + llX0Z + llXY0 + llXYZ) / 4.0f; ll3 = (llX0z + llX00 + llXYz + llXY0) / 4.0f; ll2 = (llXyz + llXy0 + llX0z + llX00) / 4.0f; } else ll1 = ll2 = ll3 = ll4 = llX00; c1r = c2r = c3r = c4r = (tint5 ? pBaseRed : 1.0f) * 0.6f; c1g = c2g = c3g = c4g = (tint5 ? pBaseGreen : 1.0f) * 0.6f; c1b = c2b = c3b = c4b = (tint5 ? pBaseBlue : 1.0f) * 0.6f; c1r *= ll1; c1g *= ll1; c1b *= ll1; c2r *= ll2; c2g *= ll2; c2b *= ll2; c3r *= ll3; c3g *= ll3; c3b *= ll3; c4r *= ll4; c4g *= ll4; c4b *= ll4; renderEast(tt, (float) pX, (float) pY, (float) pZ, tt->getTexture(level, pX, pY, pZ, 5)); i = true; } applyAmbienceOcclusion = false; return i; } bool TileRenderer::tesselateCactusInWorld(Tile* tt, int x, int y, int z) { int col = tt->getColor(level, x, y, z); float r = ((col >> 16) & 0xff) / 255.0f; float g = ((col >> 8) & 0xff) / 255.0f; float b = ((col) & 0xff) / 255.0f; return tesselateCactusInWorld(tt, x, y, z, r, g, b); } bool TileRenderer::tesselateCactusInWorld(Tile* tt, int x, int y, int z, float r, float g, float b) { Tesselator& t = Tesselator::instance; bool changed = false; float c10 = 0.5f; float c11 = 1; float c2 = 0.8f; float c3 = 0.6f; float r10 = c10 * r; float r11 = c11 * r; float r2 = c2 * r; float r3 = c3 * r; float g10 = c10 * g; float g11 = c11 * g; float g2 = c2 * g; float g3 = c3 * g; float b10 = c10 * b; float b11 = c11 * b; float b2 = c2 * b; float b3 = c3 * b; float s = 1 / 16.0f; const float X = (float)x; const float Y = (float)y; const float Z = (float)z; float centerBrightness = tt->getBrightness(level, x, y, z); if (noCulling || tt->shouldRenderFace(level, x, y - 1, z, 0)) { float br = tt->getBrightness(level, x, y - 1, z); // if (Tile::lightEmission[tt->id] > br*Level.MAX_BRIGHTNESS) br = // Tile::lightEmission[tt->id]/Level.MAX_BRIGHTNESS; t.color(r10 * br, g10 * br, b10 * br); renderFaceDown(tt, X, Y, Z, tt->getTexture(level, x, y, z, 0)); changed = true; } if (noCulling || tt->shouldRenderFace(level, x, y + 1, z, 1)) { float br = tt->getBrightness(level, x, y + 1, z); if (tt->yy1 != 1 && !tt->material->isLiquid()) br = centerBrightness; // if (Tile::lightEmission[tt->id] > br*Level.MAX_BRIGHTNESS) br = // Tile::lightEmission[tt->id]/Level.MAX_BRIGHTNESS; t.color(r11 * br, g11 * br, b11 * br); renderFaceUp(tt, X, Y, Z, tt->getTexture(level, x, y, z, 1)); changed = true; } if (noCulling || tt->shouldRenderFace(level, x, y, z - 1, 2)) { float br = tt->getBrightness(level, x, y, z - 1); if (tt->zz0 > 0) br = centerBrightness; // if (Tile::lightEmission[tt->id] > br*Level.MAX_BRIGHTNESS) br = // Tile::lightEmission[tt->id]/Level.MAX_BRIGHTNESS; t.color(r2 * br, g2 * br, b2 * br); t.addOffset(0, 0, s); renderNorth(tt, X, Y, Z, tt->getTexture(level, x, y, z, 2)); t.addOffset(0, 0, -s); changed = true; } if (noCulling || tt->shouldRenderFace(level, x, y, z + 1, 3)) { float br = tt->getBrightness(level, x, y, z + 1); if (tt->zz1 < 1) br = centerBrightness; // if (Tile::lightEmission[tt->id] > br*Level.MAX_BRIGHTNESS) br = // Tile::lightEmission[tt->id]/Level.MAX_BRIGHTNESS; t.color(r2 * br, g2 * br, b2 * br); t.addOffset(0, 0, -s); renderSouth(tt, X, Y, Z, tt->getTexture(level, x, y, z, 3)); t.addOffset(0, 0, s); changed = true; } if (noCulling || tt->shouldRenderFace(level, x - 1, y, z, 4)) { float br = tt->getBrightness(level, x - 1, y, z); if (tt->xx0 > 0) br = centerBrightness; // if (Tile::lightEmission[tt->id] > br*Level.MAX_BRIGHTNESS) br = // Tile::lightEmission[tt->id]/Level.MAX_BRIGHTNESS; t.color(r3 * br, g3 * br, b3 * br); t.addOffset(s, 0, 0); renderWest(tt, X, Y, Z, tt->getTexture(level, x, y, z, 4)); t.addOffset(-s, 0, 0); changed = true; } if (noCulling || tt->shouldRenderFace(level, x + 1, y, z, 5)) { float br = tt->getBrightness(level, x + 1, y, z); if (tt->xx1 < 1) br = centerBrightness; // if (Tile::lightEmission[tt->id] > br*Level.MAX_BRIGHTNESS) br = // Tile::lightEmission[tt->id]/Level.MAX_BRIGHTNESS; t.color(r3 * br, g3 * br, b3 * br); t.addOffset(-s, 0, 0); renderEast(tt, X, Y, Z, tt->getTexture(level, x, y, z, 5)); t.addOffset(s, 0, 0); changed = true; } return changed; } bool TileRenderer::tesselateFenceInWorld(FenceTile* tt, int x, int y, int z) { bool changed = true; float a = 6 / 16.0f; float b = 10 / 16.0f; tt->setShape(a, 0, a, b, 1, b); tesselateBlockInWorld(tt, x, y, z); bool vertical = false; bool horizontal = false; bool l = tt->connectsTo(level, x - 1, y, z); bool r = tt->connectsTo(level, x + 1, y, z); bool u = tt->connectsTo(level, x, y, z - 1); bool d = tt->connectsTo(level, x, y, z + 1); if (l || r) vertical = true; if (u || d) horizontal = true; if (!vertical && !horizontal) vertical = true; a = 7 / 16.0f; b = 9 / 16.0f; float h0 = 12 / 16.0f; float h1 = 15 / 16.0f; float x0 = l ? 0 : a; float x1 = r ? 1 : b; float z0 = u ? 0 : a; float z1 = d ? 1 : b; if (vertical) { tt->setShape(x0, h0, a, x1, h1, b); tesselateBlockInWorld(tt, x, y, z); } if (horizontal) { tt->setShape(a, h0, z0, b, h1, z1); tesselateBlockInWorld(tt, x, y, z); } h0 = 6 / 16.0f; h1 = 9 / 16.0f; if (vertical) { tt->setShape(x0, h0, a, x1, h1, b); tesselateBlockInWorld(tt, x, y, z); } if (horizontal) { tt->setShape(a, h0, z0, b, h1, z1); tesselateBlockInWorld(tt, x, y, z); } tt->setShape(0, 0, 0, 1, 1, 1); return changed; } bool TileRenderer::tesselateFenceGateInWorld(FenceGateTile* tt, int x, int y, int z) { bool changed = true; int data = level->getData(x, y, z); bool isOpen = FenceGateTile::isOpen(data); int direction = FenceGateTile::getDirection(data); const float h00 = 6 / 16.0f; const float h01 = 9 / 16.0f; const float h10 = 12 / 16.0f; const float h11 = 15 / 16.0f; const float h20 = 5 / 16.0f; const float h21 = 16 / 16.0f; // edge sticks if (direction == Direction::EAST || direction == Direction::WEST) { float x0 = 7 / 16.0f; float x1 = 9 / 16.0f; float z0 = 0 / 16.0f; float z1 = 2 / 16.0f; tt->setShape(x0, h20, z0, x1, h21, z1); tesselateBlockInWorld(tt, x, y, z); z0 = 14 / 16.0f; z1 = 16 / 16.0f; tt->setShape(x0, h20, z0, x1, h21, z1); tesselateBlockInWorld(tt, x, y, z); } else { float x0 = 0 / 16.0f; float x1 = 2 / 16.0f; float z0 = 7 / 16.0f; float z1 = 9 / 16.0f; tt->setShape(x0, h20, z0, x1, h21, z1); tesselateBlockInWorld(tt, x, y, z); x0 = 14 / 16.0f; x1 = 16 / 16.0f; tt->setShape(x0, h20, z0, x1, h21, z1); tesselateBlockInWorld(tt, x, y, z); } if (!isOpen) { if (direction == Direction::EAST || direction == Direction::WEST) { float x0 = 7 / 16.0f; float x1 = 9 / 16.0f; float z0 = 6 / 16.0f; float z1 = 8 / 16.0f; tt->setShape(x0, h00, z0, x1, h11, z1); tesselateBlockInWorld(tt, x, y, z); z0 = 8 / 16.0f; z1 = 10 / 16.0f; tt->setShape(x0, h00, z0, x1, h11, z1); tesselateBlockInWorld(tt, x, y, z); z0 = 10 / 16.0f; z1 = 14 / 16.0f; tt->setShape(x0, h00, z0, x1, h01, z1); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x0, h10, z0, x1, h11, z1); tesselateBlockInWorld(tt, x, y, z); z0 = 2 / 16.0f; z1 = 6 / 16.0f; tt->setShape(x0, h00, z0, x1, h01, z1); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x0, h10, z0, x1, h11, z1); tesselateBlockInWorld(tt, x, y, z); } else { float x0 = 6 / 16.0f; float x1 = 8 / 16.0f; float z0 = 7 / 16.0f; float z1 = 9 / 16.0f; tt->setShape(x0, h00, z0, x1, h11, z1); tesselateBlockInWorld(tt, x, y, z); x0 = 8 / 16.0f; x1 = 10 / 16.0f; tt->setShape(x0, h00, z0, x1, h11, z1); tesselateBlockInWorld(tt, x, y, z); x0 = 10 / 16.0f; x1 = 14 / 16.0f; tt->setShape(x0, h00, z0, x1, h01, z1); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x0, h10, z0, x1, h11, z1); tesselateBlockInWorld(tt, x, y, z); x0 = 2 / 16.0f; x1 = 6 / 16.0f; tt->setShape(x0, h00, z0, x1, h01, z1); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x0, h10, z0, x1, h11, z1); tesselateBlockInWorld(tt, x, y, z); } } else { if (direction == Direction::EAST) { const float z00 = 0 / 16.0f; const float z01 = 2 / 16.0f; const float z10 = 14 / 16.0f; const float z11 = 16 / 16.0f; const float x0 = 9 / 16.0f; const float x1 = 13 / 16.0f; const float x2 = 15 / 16.0f; tt->setShape(x1, h00, z00, x2, h11, z01); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x1, h00, z10, x2, h11, z11); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x0, h00, z00, x1, h01, z01); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x0, h00, z10, x1, h01, z11); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x0, h10, z00, x1, h11, z01); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x0, h10, z10, x1, h11, z11); tesselateBlockInWorld(tt, x, y, z); } else if (direction == Direction::WEST) { const float z00 = 0 / 16.0f; const float z01 = 2 / 16.0f; const float z10 = 14 / 16.0f; const float z11 = 16 / 16.0f; const float x0 = 1 / 16.0f; const float x1 = 3 / 16.0f; const float x2 = 7 / 16.0f; tt->setShape(x0, h00, z00, x1, h11, z01); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x0, h00, z10, x1, h11, z11); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x1, h00, z00, x2, h01, z01); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x1, h00, z10, x2, h01, z11); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x1, h10, z00, x2, h11, z01); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x1, h10, z10, x2, h11, z11); tesselateBlockInWorld(tt, x, y, z); } else if (direction == Direction::SOUTH) { const float x00 = 0 / 16.0f; const float x01 = 2 / 16.0f; const float x10 = 14 / 16.0f; const float x11 = 16 / 16.0f; const float z0 = 9 / 16.0f; const float z1 = 13 / 16.0f; const float z2 = 15 / 16.0f; tt->setShape(x00, h00, z1, x01, h11, z2); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x10, h00, z1, x11, h11, z2); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x00, h00, z0, x01, h01, z1); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x10, h00, z0, x11, h01, z1); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x00, h10, z0, x01, h11, z1); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x10, h10, z0, x11, h11, z1); tesselateBlockInWorld(tt, x, y, z); } else if (direction == Direction::NORTH) { const float x00 = 0 / 16.0f; const float x01 = 2 / 16.0f; const float x10 = 14 / 16.0f; const float x11 = 16 / 16.0f; const float z0 = 1 / 16.0f; const float z1 = 3 / 16.0f; const float z2 = 7 / 16.0f; tt->setShape(x00, h00, z0, x01, h11, z1); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x10, h00, z0, x11, h11, z1); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x00, h00, z1, x01, h01, z2); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x10, h00, z1, x11, h01, z2); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x00, h10, z1, x01, h11, z2); tesselateBlockInWorld(tt, x, y, z); tt->setShape(x10, h10, z1, x11, h11, z2); tesselateBlockInWorld(tt, x, y, z); } } tt->setShape(0, 0, 0, 1, 1, 1); return changed; } bool TileRenderer::tesselateBedInWorld(Tile *tt, int x, int y, int z) { Tesselator& t = Tesselator::instance; int data = level->getData(x, y, z); int direction = BedTile::getDirection(data); bool isHead = BedTile::isHeadPiece(data); float c10 = 0.5f; float c11 = 1; float c2 = 0.8f; float c3 = 0.6f; float r11 = c11; float g11 = c11; float b11 = c11; float r10 = c10; float r2 = c2; float r3 = c3; float g10 = c10; float g2 = c2; float g3 = c3; float b10 = c10; float b2 = c2; float b3 = c3; float centerBrightness = tt->getBrightness(level, x, y, z); // render wooden underside { t.color(r10 * centerBrightness, g10 * centerBrightness, b10 * centerBrightness); int tex = tt->getTexture(level, x, y, z, Facing::DOWN); int xt = (tex & 0xf) << 4; int yt = tex & 0xf0; float u0 = (xt) / 256.0f; float u1 = (xt + 16 - 0.01f) / 256.0f; float v0 = (yt) / 256.0f; float v1 = (yt + 16 - 0.01f) / 256.0f; float x0 = x + tt->xx0; float x1 = x + tt->xx1; float y0 = y + tt->yy0 + 3.0f / 16.0f; float z0 = z + tt->zz0; float z1 = z + tt->zz1; t.vertexUV(x0, y0, z1, u0, v1); t.vertexUV(x0, y0, z0, u0, v0); t.vertexUV(x1, y0, z0, u1, v0); t.vertexUV(x1, y0, z1, u1, v1); } // render bed top float brightness = tt->getBrightness(level, x, y + 1, z); t.color(r11 * brightness, g11 * brightness, b11 * brightness); int tex = tt->getTexture(level, x, y, z, Facing::UP); int xt = (tex & 0xf) << 4; int yt = tex & 0xf0; float u0 = (xt) / 256.0f; float u1 = (xt + 16 ) / 256.0f; float v0 = (yt) / 256.0f; float v1 = (yt + 16) / 256.0f; // Default is west float topLeftU = u0; float topRightU = u1; float topLeftV = v0; float topRightV = v0; float bottomLeftU = u0; float bottomRightU = u1; float bottomLeftV = v1; float bottomRightV = v1; if (direction == Direction::SOUTH) { // rotate 90 degrees clockwise topRightU = u0; topLeftV = v1; bottomLeftU = u1; bottomRightV = v0; } else if (direction == Direction::NORTH) { // rotate 90 degrees counter-clockwise topLeftU = u1; topRightV = v1; bottomRightU = u0; bottomLeftV = v0; } else if (direction == Direction::EAST) { // rotate 180 degrees topLeftU = u1; topRightV = v1; bottomRightU = u0; bottomLeftV = v0; topRightU = u0; topLeftV = v1; bottomLeftU = u1; bottomRightV = v0; } float x0 = x + tt->xx0; float x1 = x + tt->xx1; float y1 = y + tt->yy1; float z0 = z + tt->zz0; float z1 = z + tt->zz1; t.vertexUV(x1, y1, z1, bottomLeftU, bottomLeftV); t.vertexUV(x1, y1, z0, topLeftU, topLeftV); t.vertexUV(x0, y1, z0, topRightU, topRightV); t.vertexUV(x0, y1, z1, bottomRightU, bottomRightV); // determine which edge to skip (the one between foot and head piece) int skipEdge = Direction::DIRECTION_FACING[direction]; if (isHead) { skipEdge = Direction::DIRECTION_FACING[Direction::DIRECTION_OPPOSITE[direction]]; } // and which edge to x-flip int flipEdge = Facing::WEST; switch (direction) { case Direction::NORTH: break; case Direction::SOUTH: flipEdge = Facing::EAST; break; case Direction::EAST: flipEdge = Facing::NORTH; break; case Direction::WEST: flipEdge = Facing::SOUTH; break; } if ((skipEdge != Facing::NORTH) && (noCulling || tt->shouldRenderFace(level, x, y, z - 1, Facing::NORTH))) { float br = tt->getBrightness(level, x, y, z - 1); if (tt->zz0 > 0) br = centerBrightness; t.color(r2 * br, g2 * br, b2 * br); xFlipTexture = flipEdge == Facing::NORTH; renderNorth(tt, float(x), float(y), float(z), tt->getTexture(level, x, y, z, 2)); } if ((skipEdge != Facing::SOUTH) && (noCulling || tt->shouldRenderFace(level, x, y, z + 1, Facing::SOUTH))) { float br = tt->getBrightness(level, x, y, z + 1); if (tt->zz1 < 1) br = centerBrightness; t.color(r2 * br, g2 * br, b2 * br); xFlipTexture = flipEdge == Facing::SOUTH; renderSouth(tt, float(x), float(y), float(z), tt->getTexture(level, x, y, z, 3)); } if ((skipEdge != Facing::WEST) && (noCulling || tt->shouldRenderFace(level, x - 1, y, z, Facing::WEST))) { float br = tt->getBrightness(level, x - 1, y, z); if (tt->xx0 > 0) br = centerBrightness; t.color(r3 * br, g3 * br, b3 * br); xFlipTexture = flipEdge == Facing::WEST; renderWest(tt, float(x), float(y), float(z), tt->getTexture(level, x, y, z, 4)); } if ((skipEdge != Facing::EAST) && (noCulling || tt->shouldRenderFace(level, x + 1, y, z, Facing::EAST))) { float br = tt->getBrightness(level, x + 1, y, z); if (tt->xx1 < 1) br = centerBrightness; t.color(r3 * br, g3 * br, b3 * br); xFlipTexture = flipEdge == Facing::EAST; renderEast(tt, float(x), float(y), float(z), tt->getTexture(level, x, y, z, 5)); } xFlipTexture = false; return true; } bool TileRenderer::tesselateStairsInWorld( StairTile* tt, int x, int y, int z ) { tt->setBaseShape(level, x, y, z); tesselateBlockInWorld(tt, x, y, z); bool checkInnerPiece = tt->setStepShape(level, x, y, z); tesselateBlockInWorld(tt, x, y, z); if (checkInnerPiece) { if (tt->setInnerPieceShape(level, x, y, z)) { tesselateBlockInWorld(tt, x, y, z); } } // setShape(0, 0, 0, 1, 1, 1); return true; } bool TileRenderer::tesselateDoorInWorld( Tile* tt, int x, int y, int z ) { Tesselator& t = Tesselator::instance; DoorTile* dt = (DoorTile*) tt; bool changed = false; float c10 = 0.5f; float c11 = 1; float c2 = 0.8f; float c3 = 0.6f; float centerBrightness = tt->getBrightness(level, x, y, z); { float br = tt->getBrightness(level, x, y - 1, z); if (dt->yy0 > 0) br = centerBrightness; if (Tile::lightEmission[tt->id] > 0) br = 1.0f; t.color(c10 * br, c10 * br, c10 * br); renderFaceDown(tt, (float)x, (float)y, (float)z, tt->getTexture(level, x, y, z, 0)); changed = true; } { float br = tt->getBrightness(level, x, y + 1, z); if (dt->yy1 < 1) br = centerBrightness; if (Tile::lightEmission[tt->id] > 0) br = 1.0f; t.color(c11 * br, c11 * br, c11 * br); renderFaceUp(tt, (float)x, (float)y, (float)z, tt->getTexture(level, x, y, z, 1)); changed = true; } { float br = tt->getBrightness(level, x, y, z - 1); if (dt->zz0 > 0) br = centerBrightness; if (Tile::lightEmission[tt->id] > 0) br = 1.0f; t.color(c2 * br, c2 * br, c2 * br); int tex = tt->getTexture(level, x, y, z, 2); if (tex < 0) { xFlipTexture = true; tex = -tex; } renderNorth(tt, (float)x, (float)y, (float)z, tex); changed = true; xFlipTexture = false; } { float br = tt->getBrightness(level, x, y, z + 1); if (dt->zz1 < 1) br = centerBrightness; if (Tile::lightEmission[tt->id] > 0) br = 1.0f; t.color(c2 * br, c2 * br, c2 * br); int tex = tt->getTexture(level, x, y, z, 3); if (tex < 0) { xFlipTexture = true; tex = -tex; } renderSouth(tt, (float)x, (float)y, (float)z, tex); changed = true; xFlipTexture = false; } { float br = tt->getBrightness(level, x - 1, y, z); if (dt->xx0 > 0) br = centerBrightness; if (Tile::lightEmission[tt->id] > 0) br = 1.0f; t.color(c3 * br, c3 * br, c3 * br); int tex = tt->getTexture(level, x, y, z, 4); if (tex < 0) { xFlipTexture = true; tex = -tex; } renderWest(tt, (float)x, (float)y, (float)z, tex); changed = true; xFlipTexture = false; } { float br = tt->getBrightness(level, x + 1, y, z); if (dt->xx1 < 1) br = centerBrightness; if (Tile::lightEmission[tt->id] > 0) br = 1.0f; t.color(c3 * br, c3 * br, c3 * br); int tex = tt->getTexture(level, x, y, z, 5); if (tex < 0) { xFlipTexture = true; tex = -tex; } renderEast(tt, (float)x, (float)y, (float)z, tex); changed = true; xFlipTexture = false; } return changed; } bool TileRenderer::tesselateRowInWorld( Tile* tt, int x, int y, int z ) { Tesselator& t = Tesselator::instance; float br = tt->getBrightness(level, x, y, z); t.color(br, br, br); tesselateRowTexture(tt, level->getData(x, y, z), float(x), y - 1 / 16.0f, float(z)); return true; } void TileRenderer::renderFaceDown( Tile* tt, float x, float y, float z, int tex ) { Tesselator& t = Tesselator::instance; if (fixedTexture >= 0) tex = fixedTexture; int xt = (tex & 0xf) << 4; int yt = tex & 0xf0; float u0 = (xt + tt->xx0 * 16) / 256.0f; float u1 = (xt + tt->xx1 * 16 - 0.01f) / 256.0f; float v0 = (yt + tt->zz0 * 16) / 256.0f; float v1 = (yt + tt->zz1 * 16 - 0.01f) / 256.0f; if (tt->xx0 < 0 || tt->xx1 > 1) { u0 = (xt + 0 * 15.99f) / 256.0f; u1 = (xt + 1 * 15.99f) / 256.0f; } if (tt->zz0 < 0 || tt->zz1 > 1) { v0 = (yt + 0 * 15.99f) / 256.0f; v1 = (yt + 1 * 15.99f) / 256.0f; } float x0 = x + tt->xx0; float x1 = x + tt->xx1; float y0 = y + tt->yy0; float z0 = z + tt->zz0; float z1 = z + tt->zz1; if (applyAmbienceOcclusion) { t.color(c1r, c1g, c1b); t.vertexUV(x0, y0, z1, u0, v1); t.color(c2r, c2g, c2b); t.vertexUV(x0, y0, z0, u0, v0); t.color(c3r, c3g, c3b); t.vertexUV(x1, y0, z0, u1, v0); t.color(c4r, c4g, c4b); t.vertexUV(x1, y0, z1, u1, v1); } else { t.vertexUV(x0, y0, z1, u0, v1); t.vertexUV(x0, y0, z0, u0, v0); t.vertexUV(x1, y0, z0, u1, v0); t.vertexUV(x1, y0, z1, u1, v1); } } void TileRenderer::renderFaceUp( Tile* tt, float x, float y, float z, int tex ) { Tesselator& t = Tesselator::instance; if (fixedTexture >= 0) tex = fixedTexture; int xt = (tex & 0xf) << 4; int yt = tex & 0xf0; float u0 = (xt + tt->xx0 * 16) / 256.0f; float u1 = (xt + tt->xx1 * 16 - 0.01f) / 256.0f; float v0 = (yt + tt->zz0 * 16) / 256.0f; float v1 = (yt + tt->zz1 * 16 - 0.01f) / 256.0f; if (tt->xx0 < 0 || tt->xx1 > 1) { u0 = (xt + 0 * 15.99f) / 256.0f; u1 = (xt + 1 * 15.99f) / 256.0f; } if (tt->zz0 < 0 || tt->zz1 > 1) { v0 = (yt + 0 * 15.99f) / 256.0f; v1 = (yt + 1 * 15.99f) / 256.0f; } float x0 = x + tt->xx0; float x1 = x + tt->xx1; float y1 = y + tt->yy1; float z0 = z + tt->zz0; float z1 = z + tt->zz1; if (applyAmbienceOcclusion) { t.color(c1r, c1g, c1b); t.vertexUV(x1, y1, z1, u1, v1); t.color(c2r, c2g, c2b); t.vertexUV(x1, y1, z0, u1, v0); t.color(c3r, c3g, c3b); t.vertexUV(x0, y1, z0, u0, v0); t.color(c4r, c4g, c4b); t.vertexUV(x0, y1, z1, u0, v1); } else { t.vertexUV(x1, y1, z1, u1, v1); t.vertexUV(x1, y1, z0, u1, v0); t.vertexUV(x0, y1, z0, u0, v0); t.vertexUV(x0, y1, z1, u0, v1); } } void TileRenderer::renderNorth( Tile* tt, float x, float y, float z, int tex ) { Tesselator& t = Tesselator::instance; if (fixedTexture >= 0) tex = fixedTexture; int xt = (tex & 0xf) << 4; int yt = tex & 0xf0; float u0 = (xt + tt->xx0 * 16) / 256.0f; float u1 = (xt + tt->xx1 * 16 - 0.01f) / 256.0f; float v0 = (yt + 16 - tt->yy1 * 16) / 256.0f; float v1 = (yt + 16 - tt->yy0 * 16 - 0.01f) / 256.0f; if (xFlipTexture) { float tmp = u0; u0 = u1; u1 = tmp; } if (tt->xx0 < 0 || tt->xx1 > 1) { u0 = (xt + 0 * 15.99f) / 256.0f; u1 = (xt + 1 * 15.99f) / 256.0f; } if (tt->yy0 < 0 || tt->yy1 > 1) { v0 = (yt + 0 * 15.99f) / 256.0f; v1 = (yt + 1 * 15.99f) / 256.0f; } float x0 = x + tt->xx0; float x1 = x + tt->xx1; float y0 = y + tt->yy0; float y1 = y + tt->yy1; float z0 = z + tt->zz0; if (applyAmbienceOcclusion) { t.color(c1r, c1g, c1b); t.vertexUV(x0, y1, z0, u1, v0); t.color(c2r, c2g, c2b); t.vertexUV(x1, y1, z0, u0, v0); t.color(c3r, c3g, c3b); t.vertexUV(x1, y0, z0, u0, v1); t.color(c4r, c4g, c4b); t.vertexUV(x0, y0, z0, u1, v1); } else { t.vertexUV(x0, y1, z0, u1, v0); t.vertexUV(x1, y1, z0, u0, v0); t.vertexUV(x1, y0, z0, u0, v1); t.vertexUV(x0, y0, z0, u1, v1); } } void TileRenderer::renderSouth( Tile* tt, float x, float y, float z, int tex ) { Tesselator& t = Tesselator::instance; if (fixedTexture >= 0) tex = fixedTexture; int xt = (tex & 0xf) << 4; int yt = tex & 0xf0; float u0 = (xt + tt->xx0 * 16) / 256.0f; float u1 = (xt + tt->xx1 * 16 - 0.01f) / 256.0f; float v0 = (yt + 16 - tt->yy1 * 16) / 256.0f; float v1 = (yt + 16 - tt->yy0 * 16 - 0.01f) / 256.0f; if (xFlipTexture) { float tmp = u0; u0 = u1; u1 = tmp; } if (tt->xx0 < 0 || tt->xx1 > 1) { u0 = (xt + 0 * 15.99f) / 256.0f; u1 = (xt + 1 * 15.99f) / 256.0f; } if (tt->yy0 < 0 || tt->yy1 > 1) { v0 = (yt + 0 * 15.99f) / 256.0f; v1 = (yt + 1 * 15.99f) / 256.0f; } float x0 = x + tt->xx0; float x1 = x + tt->xx1; float y0 = y + tt->yy0; float y1 = y + tt->yy1; float z1 = z + tt->zz1; if (applyAmbienceOcclusion) { t.color(c1r, c1g, c1b); t.vertexUV(x0, y1, z1, u0, v0); t.color(c2r, c2g, c2b); t.vertexUV(x0, y0, z1, u0, v1); t.color(c3r, c3g, c3b); t.vertexUV(x1, y0, z1, u1, v1); t.color(c4r, c4g, c4b); t.vertexUV(x1, y1, z1, u1, v0); } else { t.vertexUV(x0, y1, z1, u0, v0); t.vertexUV(x0, y0, z1, u0, v1); t.vertexUV(x1, y0, z1, u1, v1); t.vertexUV(x1, y1, z1, u1, v0); } } void TileRenderer::renderWest( Tile* tt, float x, float y, float z, int tex ) { Tesselator& t = Tesselator::instance; if (fixedTexture >= 0) tex = fixedTexture; int xt = (tex & 0xf) << 4; int yt = tex & 0xf0; float u0 = (xt + tt->zz0 * 16) / 256.0f; float u1 = (xt + tt->zz1 * 16 - 0.01f) / 256.0f; float v0 = (yt + 16 - tt->yy1 * 16) / 256.0f; float v1 = (yt + 16 - tt->yy0 * 16 - 0.01f) / 256.0f; if (xFlipTexture) { float tmp = u0; u0 = u1; u1 = tmp; } if (tt->zz0 < 0 || tt->zz1 > 1) { u0 = (xt + 0 * 15.99f) / 256.0f; u1 = (xt + 1 * 15.99f) / 256.0f; } if (tt->yy0 < 0 || tt->yy1 > 1) { v0 = (yt + 0 * 15.99f) / 256.0f; v1 = (yt + 1 * 15.99f) / 256.0f; } float x0 = x + tt->xx0; float y0 = y + tt->yy0; float y1 = y + tt->yy1; float z0 = z + tt->zz0; float z1 = z + tt->zz1; if (applyAmbienceOcclusion) { t.color(c1r, c1g, c1b); t.vertexUV(x0, y1, z1, u1, v0); t.color(c2r, c2g, c2b); t.vertexUV(x0, y1, z0, u0, v0); t.color(c3r, c3g, c3b); t.vertexUV(x0, y0, z0, u0, v1); t.color(c4r, c4g, c4b); t.vertexUV(x0, y0, z1, u1, v1); } else { t.vertexUV(x0, y1, z1, u1, v0); t.vertexUV(x0, y1, z0, u0, v0); t.vertexUV(x0, y0, z0, u0, v1); t.vertexUV(x0, y0, z1, u1, v1); } } void TileRenderer::renderEast( Tile* tt, float x, float y, float z, int tex ) { Tesselator& t = Tesselator::instance; if (fixedTexture >= 0) tex = fixedTexture; int xt = (tex & 0xf) << 4; int yt = tex & 0xf0; float u0 = (xt + tt->zz0 * 16) / 256.0f; float u1 = (xt + tt->zz1 * 16 - 0.01f) / 256.0f; float v0 = (yt + 16 - tt->yy1 * 16) / 256.0f; float v1 = (yt + 16 - tt->yy0 * 16 - 0.01f) / 256.0f; if (xFlipTexture) { float tmp = u0; u0 = u1; u1 = tmp; } if (tt->zz0 < 0 || tt->zz1 > 1) { u0 = (xt + 0 * 15.99f) / 256.0f; u1 = (xt + 1 * 15.99f) / 256.0f; } if (tt->yy0 < 0 || tt->yy1 > 1) { v0 = (yt + 0 * 15.99f) / 256.0f; v1 = (yt + 1 * 15.99f) / 256.0f; } float x1 = x + tt->xx1; float y0 = y + tt->yy0; float y1 = y + tt->yy1; float z0 = z + tt->zz0; float z1 = z + tt->zz1; if (applyAmbienceOcclusion) { t.color(c1r, c1g, c1b); t.vertexUV(x1, y0, z1, u0, v1); t.color(c2r, c2g, c2b); t.vertexUV(x1, y0, z0, u1, v1); t.color(c3r, c3g, c3b); t.vertexUV(x1, y1, z0, u1, v0); t.color(c4r, c4g, c4b); t.vertexUV(x1, y1, z1, u0, v0); } else { t.vertexUV(x1, y0, z1, u0, v1); t.vertexUV(x1, y0, z0, u1, v1); t.vertexUV(x1, y1, z0, u1, v0); t.vertexUV(x1, y1, z1, u0, v0); } } void TileRenderer::renderTile( Tile* tile, int data ) { Tesselator& t = Tesselator::instance; t.color(0xff, 0xff, 0xff); int shape = tile->getRenderShape(); if (shape == Tile::SHAPE_BLOCK) { tile->updateDefaultShape(); t.addOffset(-0.5f, -0.5f, -0.5f); t.begin(); renderFaceDown(tile, 0, 0, 0, tile->getTexture(0, data)); renderFaceUp(tile, 0, 0, 0, tile->getTexture(1, data)); renderNorth(tile, 0, 0, 0, tile->getTexture(2, data)); renderSouth(tile, 0, 0, 0, tile->getTexture(3, data)); renderWest(tile, 0, 0, 0, tile->getTexture(4, data)); renderEast(tile, 0, 0, 0, tile->getTexture(5, data)); t.draw(); t.addOffset(0.5f, 0.5f, 0.5f); } else if (shape == Tile::SHAPE_CROSS_TEXTURE) { t.begin(); tesselateCrossTexture(tile, data, -0.5f, -0.5f, -0.5f); t.draw(); } else if(shape == Tile::SHAPE_STEM) { t.begin(); tile->updateDefaultShape(); tesselateStemTexture(tile, data, tile->yy1, -0.5f, -0.5f, -0.5f); t.draw(); } else if (shape == Tile::SHAPE_CACTUS) { tile->updateDefaultShape(); t.offset(-0.5f, -0.5f, -0.5f); float s = 1 / 16.0f; t.begin(); renderFaceDown(tile, 0, 0, 0, tile->getTexture(0)); renderFaceUp(tile, 0, 0, 0, tile->getTexture(1)); t.addOffset(0, 0, s); renderNorth(tile, 0, 0, 0, tile->getTexture(2)); t.addOffset(0, 0, -s); t.addOffset(0, 0, -s); renderSouth(tile, 0, 0, 0, tile->getTexture(3)); t.addOffset(0, 0, s); t.addOffset(s, 0, 0); renderWest(tile, 0, 0, 0, tile->getTexture(4)); t.addOffset(-s, 0, 0); t.addOffset(-s, 0, 0); renderEast(tile, 0, 0, 0, tile->getTexture(5)); t.addOffset(s, 0, 0); t.draw(); t.offset(0, 0, 0);//0.5f, 0.5f, 0.5f); } else if (shape == Tile::SHAPE_ROWS) { t.begin(); t.normal(0, -1, 0); tesselateRowTexture(tile, data, -0.5f, -0.5f, -0.5f); //} else if (shape == Tile::SHAPE_TORCH) { //// t.begin(); //// t.normal(0, -1, 0); //// tesselateTorch(tile, -0.5f, -0.5f, -0.5f, 0, 0); //// t.end(); } else if (shape == Tile::SHAPE_ENTITYTILE_ANIMATED) { EntityTileRenderer::instance->render(tile, data, 1.0f); //glEnable(GL_RESCALE_NORMAL); } else if (shape == Tile::SHAPE_STAIRS) { t.addOffset(-0.5f, -0.5f, -0.5f); t.begin(); for (int i = 0; i < 2; i++) { if (i == 0) tile->setShape(0, 0, 0, 1, 1, 0.5f); if (i == 1) tile->setShape(0, 0, 0.5f, 1, 0.5f, 1); renderFaceDown(tile, 0, 0, 0, tile->getTexture(0)); renderFaceUp(tile, 0, 0, 0, tile->getTexture(1)); renderNorth(tile, 0, 0, 0, tile->getTexture(2)); renderSouth(tile, 0, 0, 0, tile->getTexture(3)); renderWest(tile, 0, 0, 0, tile->getTexture(4)); renderEast(tile, 0, 0, 0, tile->getTexture(5)); } t.draw(); t.addOffset(0.5f, 0.5f, 0.5f); } else if (shape == Tile::SHAPE_FENCE) { t.addOffset(-0.5f, -0.5f, -0.5f); t.begin(); for (int i = 0; i < 4; i++) { float w = 2 / 16.0f; if (i == 0) tile->setShape(0.5f - w, 0, 0, 0.5f + w, 1, w * 2); if (i == 1) tile->setShape(0.5f - w, 0, 1 - w * 2, 0.5f + w, 1, 1); w = 1 / 16.0f; if (i == 2) tile->setShape(0.5f - w, 1 - w * 3, -w * 2, 0.5f + w, 1 - w, 1 + w * 2); if (i == 3) tile->setShape(0.5f - w, 0.5f - w * 3, -w * 2, 0.5f + w, 0.5f - w, 1 + w * 2); renderFaceDown(tile, 0, 0, 0, tile->getTexture(0)); renderFaceUp(tile, 0, 0, 0, tile->getTexture(1)); renderNorth(tile, 0, 0, 0, tile->getTexture(2)); renderSouth(tile, 0, 0, 0, tile->getTexture(3)); renderWest(tile, 0, 0, 0, tile->getTexture(4)); renderEast(tile, 0, 0, 0, tile->getTexture(5)); } t.draw(); t.addOffset(0.5f, 0.5f, 0.5f); tile->setShape(0, 0, 0, 1, 1, 1); } else if (shape == Tile::SHAPE_FENCE_GATE) { t.addOffset(-0.5f, -0.5f, -0.5f); t.begin(); for (int i = 0; i < 3; i++) { float w = 1 / 16.0f; if (i == 0) tile->setShape(0.5f - w, .3f, 0, 0.5f + w, 1, w * 2); if (i == 1) tile->setShape(0.5f - w, .3f, 1 - w * 2, 0.5f + w, 1, 1); if (i == 2) tile->setShape(0.5f - w, .5f, w * 2, 0.5f + w, 1 - w, 1 - w * 2); renderFaceUp(tile, 0, 0, 0, tile->getTexture(0)); renderFaceDown(tile, 0, 0, 0, tile->getTexture(1)); renderNorth(tile, 0, 0, 0, tile->getTexture(2)); renderSouth(tile, 0, 0, 0, tile->getTexture(3)); renderWest(tile, 0, 0, 0, tile->getTexture(4)); renderEast(tile, 0, 0, 0, tile->getTexture(5)); } t.draw(); t.addOffset(0.5f, 0.5f, 0.5f); tile->setShape(0, 0, 0, 1, 1, 1); } } bool TileRenderer::canRender( int renderShape ) { if (renderShape == Tile::SHAPE_BLOCK) return true; if (renderShape == Tile::SHAPE_CACTUS) return true; if (renderShape == Tile::SHAPE_STAIRS) return true; if (renderShape == Tile::SHAPE_FENCE) return true; if (renderShape == Tile::SHAPE_FENCE_GATE) return true; //if (renderShape == Tile::SHAPE_CROSS_TEXTURE) return true; //if (renderShape == Tile::SHAPE_ENTITYTILE_ANIMATED) return true; return false; } void TileRenderer::renderGuiTile( Tile* tile, int data ) { Tesselator& t = Tesselator::instance; int shape = tile->getRenderShape(); if (shape == Tile::SHAPE_BLOCK) { tile->updateDefaultShape(); t.begin(); t.addOffset(-0.5f, -0.5f, -0.5f); t.color(0xff, 0xff, 0xff); renderFaceUp(tile, 0, 0, 0, tile->getTexture(1, data)); renderFaceDown(tile, 0, 0, 0, tile->getTexture(0, data)); t.color(0x80, 0x80, 0x80); renderNorth(tile, 0, 0, 0, tile->getTexture(2, data)); renderSouth(tile, 0, 0, 0, tile->getTexture(3, data)); t.color(0xbb, 0xbb, 0xbb); renderEast(tile, 0, 0, 0, tile->getTexture(5, data)); renderWest(tile, 0, 0, 0, tile->getTexture(4, data)); t.draw(); t.addOffset(0.5f, 0.5f, 0.5f); } else if (shape == Tile::SHAPE_CROSS_TEXTURE) { t.begin(); //t.normal(0, -1, 0); tesselateCrossTexture(tile, data, -0.5f, -0.5f, -0.5f); //t.end(); t.draw(); } else if (shape == Tile::SHAPE_CACTUS) { tile->updateDefaultShape(); t.begin(); t.offset(-0.5f, -0.5f, -0.5f); float s = 1 / 16.0f; t.color(0xff, 0xff, 0xff); renderFaceDown(tile, 0, 0, 0, tile->getTexture(0)); renderFaceUp(tile, 0, 0, 0, tile->getTexture(1)); t.color(0x80, 0x80, 0x80); t.addOffset(0, 0, s); renderNorth(tile, 0, 0, 0, tile->getTexture(2)); t.addOffset(0, 0, -s-s); renderSouth(tile, 0, 0, 0, tile->getTexture(3)); t.color(0xbb, 0xbb, 0xbb); t.addOffset(s, 0, s); renderWest(tile, 0, 0, 0, tile->getTexture(4)); t.addOffset(-s-s, 0, 0); renderEast(tile, 0, 0, 0, tile->getTexture(5)); t.draw(); t.addOffset(s+0.5f, 0.5f, 0.5f); } else if (shape == Tile::SHAPE_STAIRS) { t.offset(-0.5f, -0.5f, -0.5f); t.begin(); for (int i = 0; i < 2; i++) { if (i == 0) tile->setShape(0, 0, 0, 1, 1, 0.5f); if (i == 1) tile->setShape(0, 0, 0.5f, 1, 0.5f, 1); t.color(0xff, 0xff, 0xff); renderFaceDown(tile, 0, 0, 0, tile->getTexture(0)); renderFaceUp(tile, 0, 0, 0, tile->getTexture(1)); t.color(0x80, 0x80, 0x80); renderNorth(tile, 0, 0, 0, tile->getTexture(2)); renderSouth(tile, 0, 0, 0, tile->getTexture(3)); t.color(0xbb, 0xbb, 0xbb); renderWest(tile, 0, 0, 0, tile->getTexture(4)); renderEast(tile, 0, 0, 0, tile->getTexture(5)); } t.draw(); t.offset(0, 0, 0); } else if (shape == Tile::SHAPE_FENCE) { t.addOffset(-0.5f, -0.5f, -0.5f); t.begin(); for (int i = 0; i < 4; i++) { float w = 2 / 16.0f; if (i == 0) tile->setShape(0.5f - w, 0, 0, 0.5f + w, 1, w * 2); if (i == 1) tile->setShape(0.5f - w, 0, 1 - w * 2, 0.5f + w, 1, 1); w = 1 / 16.0f; if (i == 2) tile->setShape(0.5f - w, 1 - w * 3, -w * 2, 0.5f + w, 1 - w, 1 + w * 2); if (i == 3) tile->setShape(0.5f - w, 0.5f - w * 3, -w * 2, 0.5f + w, 0.5f - w, 1 + w * 2); t.color(0xff, 0xff, 0xff); renderFaceDown(tile, 0, 0, 0, tile->getTexture(0)); renderFaceUp(tile, 0, 0, 0, tile->getTexture(1)); t.color(0x80, 0x80, 0x80); renderNorth(tile, 0, 0, 0, tile->getTexture(2)); renderSouth(tile, 0, 0, 0, tile->getTexture(3)); t.color(0xbb, 0xbb, 0xbb); renderWest(tile, 0, 0, 0, tile->getTexture(4)); renderEast(tile, 0, 0, 0, tile->getTexture(5)); } t.draw(); t.addOffset(0.5f, 0.5f, 0.5f); tile->setShape(0, 0, 0, 1, 1, 1); } else if (shape == Tile::SHAPE_FENCE_GATE) { t.addOffset(-0.5f, -0.5f, -0.5f); t.begin(); for (int i = 0; i < 3; i++) { float w = 1 / 16.0f; if (i == 0) tile->setShape(0.5f - w, .3f, 0, 0.5f + w, 1, w * 2); if (i == 1) tile->setShape(0.5f - w, .3f, 1 - w * 2, 0.5f + w, 1, 1); w = 1 / 16.0f; if (i == 2) tile->setShape(0.5f - w, .5f, 0, 0.5f + w, 1 - w, 1); t.color(0xff, 0xff, 0xff); renderFaceUp(tile, 0, 0, 0, tile->getTexture(0)); renderFaceDown(tile, 0, 0, 0, tile->getTexture(1)); t.color(0x80, 0x80, 0x80); renderNorth(tile, 0, 0, 0, tile->getTexture(2)); renderSouth(tile, 0, 0, 0, tile->getTexture(3)); t.color(0xbb, 0xbb, 0xbb); renderWest(tile, 0, 0, 0, tile->getTexture(4)); renderEast(tile, 0, 0, 0, tile->getTexture(5)); } t.draw(); tile->setShape(0, 0, 0, 1, 1, 1); t.addOffset(0.5f, 0.5f, 0.5f); } } bool TileRenderer::tesselateThinFenceInWorld(ThinFenceTile* tt, int x, int y, int z) { const int depth = 128; Tesselator& t = Tesselator::instance; float br = tt->getBrightness(level, x, y, z); int col = tt->getColor(level, x, y, z); float r = ((col >> 16) & 0xff) / 255.0f; float g = ((col >> 8) & 0xff) / 255.0f; float b = ((col) & 0xff) / 255.0f; //if (GameRenderer::anaglyph3d) { // float cr = (r * 30 + g * 59 + b * 11) / 100; // float cg = (r * 30 + g * 70) / (100); // float cb = (r * 30 + b * 70) / (100); // r = cr; // g = cg; // b = cb; //} t.color(br * r, br * g, br * b); int tex = 0; int edgeTex = 0; if (fixedTexture >= 0) { tex = fixedTexture; edgeTex = fixedTexture; } else { int data = level->getData(x, y, z); tex = tt->getTexture(0, data); edgeTex = tt->getEdgeTexture(); } const int xt = (tex & 0xf) << 4; const int yt = tex & 0xf0; float u0 = (xt) / 256.0f; const float u1 = (xt + 7.99f) / 256.0f; const float u2 = (xt + 15.99f) / 256.0f; const float v0 = (yt) / 256.0f; const float v2 = (yt + 15.99f) / 256.0f; const int xet = (edgeTex & 0xf) << 4; const int yet = edgeTex & 0xf0; const float iu0 = (xet + 7) / 256.0f; const float iu1 = (xet + 8.99f) / 256.0f; const float iv0 = (yet) / 256.0f; const float iv1 = (yet + 8) / 256.0f; const float iv2 = (yet + 15.99f) / 256.0f; const float x0 = (float)x; const float x1 = x0 + .5f; const float x2 = x0 + 1; const float y0 = (float)y + 0.001f; const float y1 = y0 + 1 - 0.002f; const float z0 = (float)z; const float z1 = z0 + .5f; const float z2 = z0 + 1; const float ix0 = x0 + .5f - 1.0f / 16.0f; const float ix1 = x0 + .5f + 1.0f / 16.0f; const float iz0 = z0 + .5f - 1.0f / 16.0f; const float iz1 = z0 + .5f + 1.0f / 16.0f; const bool n = tt->attachsTo(level->getTile(x, y, z - 1)); const bool s = tt->attachsTo(level->getTile(x, y, z + 1)); const bool w = tt->attachsTo(level->getTile(x - 1, y, z)); const bool e = tt->attachsTo(level->getTile(x + 1, y, z)); const bool up = tt->shouldRenderFace(level, x, y + 1, z, Facing::UP); const bool down = tt->shouldRenderFace(level, x, y - 1, z, Facing::DOWN); const float noZFightingOffset = 0.01f; if ((w && e) || (!w && !e && !n && !s)) { t.vertexUV(x0, y1, z1, u0, v0); t.vertexUV(x0, y0, z1, u0, v2); t.vertexUV(x2, y0, z1, u2, v2); t.vertexUV(x2, y1, z1, u2, v0); t.vertexUV(x2, y1, z1, u0, v0); t.vertexUV(x2, y0, z1, u0, v2); t.vertexUV(x0, y0, z1, u2, v2); t.vertexUV(x0, y1, z1, u2, v0); if (up) { // small edge texture t.vertexUV(x0, y1 + noZFightingOffset, iz1, iu1, iv2); t.vertexUV(x2, y1 + noZFightingOffset, iz1, iu1, iv0); t.vertexUV(x2, y1 + noZFightingOffset, iz0, iu0, iv0); t.vertexUV(x0, y1 + noZFightingOffset, iz0, iu0, iv2); t.vertexUV(x2, y1 + noZFightingOffset, iz1, iu1, iv2); t.vertexUV(x0, y1 + noZFightingOffset, iz1, iu1, iv0); t.vertexUV(x0, y1 + noZFightingOffset, iz0, iu0, iv0); t.vertexUV(x2, y1 + noZFightingOffset, iz0, iu0, iv2); } else { if (y < (depth - 1) && level->isEmptyTile(x - 1, y + 1, z)) { t.vertexUV(x0, y1 + noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x1, y1 + noZFightingOffset, iz1, iu1, iv2); t.vertexUV(x1, y1 + noZFightingOffset, iz0, iu0, iv2); t.vertexUV(x0, y1 + noZFightingOffset, iz0, iu0, iv1); t.vertexUV(x1, y1 + noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x0, y1 + noZFightingOffset, iz1, iu1, iv2); t.vertexUV(x0, y1 + noZFightingOffset, iz0, iu0, iv2); t.vertexUV(x1, y1 + noZFightingOffset, iz0, iu0, iv1); } if (y < (depth - 1) && level->isEmptyTile(x + 1, y + 1, z)) { t.vertexUV(x1, y1 + noZFightingOffset, iz1, iu1, iv0); t.vertexUV(x2, y1 + noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x2, y1 + noZFightingOffset, iz0, iu0, iv1); t.vertexUV(x1, y1 + noZFightingOffset, iz0, iu0, iv0); t.vertexUV(x2, y1 + noZFightingOffset, iz1, iu1, iv0); t.vertexUV(x1, y1 + noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x1, y1 + noZFightingOffset, iz0, iu0, iv1); t.vertexUV(x2, y1 + noZFightingOffset, iz0, iu0, iv0); } } if (down) { // small edge texture t.vertexUV(x0, y0 - noZFightingOffset, iz1, iu1, iv2); t.vertexUV(x2, y0 - noZFightingOffset, iz1, iu1, iv0); t.vertexUV(x2, y0 - noZFightingOffset, iz0, iu0, iv0); t.vertexUV(x0, y0 - noZFightingOffset, iz0, iu0, iv2); t.vertexUV(x2, y0 - noZFightingOffset, iz1, iu1, iv2); t.vertexUV(x0, y0 - noZFightingOffset, iz1, iu1, iv0); t.vertexUV(x0, y0 - noZFightingOffset, iz0, iu0, iv0); t.vertexUV(x2, y0 - noZFightingOffset, iz0, iu0, iv2); } else { if (y > 1 && level->isEmptyTile(x - 1, y - 1, z)) { t.vertexUV(x0, y0 - noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x1, y0 - noZFightingOffset, iz1, iu1, iv2); t.vertexUV(x1, y0 - noZFightingOffset, iz0, iu0, iv2); t.vertexUV(x0, y0 - noZFightingOffset, iz0, iu0, iv1); t.vertexUV(x1, y0 - noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x0, y0 - noZFightingOffset, iz1, iu1, iv2); t.vertexUV(x0, y0 - noZFightingOffset, iz0, iu0, iv2); t.vertexUV(x1, y0 - noZFightingOffset, iz0, iu0, iv1); } if (y > 1 && level->isEmptyTile(x + 1, y - 1, z)) { t.vertexUV(x1, y0 - noZFightingOffset, iz1, iu1, iv0); t.vertexUV(x2, y0 - noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x2, y0 - noZFightingOffset, iz0, iu0, iv1); t.vertexUV(x1, y0 - noZFightingOffset, iz0, iu0, iv0); t.vertexUV(x2, y0 - noZFightingOffset, iz1, iu1, iv0); t.vertexUV(x1, y0 - noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x1, y0 - noZFightingOffset, iz0, iu0, iv1); t.vertexUV(x2, y0 - noZFightingOffset, iz0, iu0, iv0); } } } else if (w && !e) { // half-step towards west t.vertexUV(x0, y1, z1, u0, v0); t.vertexUV(x0, y0, z1, u0, v2); t.vertexUV(x1, y0, z1, u1, v2); t.vertexUV(x1, y1, z1, u1, v0); t.vertexUV(x1, y1, z1, u0, v0); t.vertexUV(x1, y0, z1, u0, v2); t.vertexUV(x0, y0, z1, u1, v2); t.vertexUV(x0, y1, z1, u1, v0); // small edge texture if (!s && !n) { t.vertexUV(x1, y1, iz1, iu0, iv0); t.vertexUV(x1, y0, iz1, iu0, iv2); t.vertexUV(x1, y0, iz0, iu1, iv2); t.vertexUV(x1, y1, iz0, iu1, iv0); t.vertexUV(x1, y1, iz0, iu0, iv0); t.vertexUV(x1, y0, iz0, iu0, iv2); t.vertexUV(x1, y0, iz1, iu1, iv2); t.vertexUV(x1, y1, iz1, iu1, iv0); } if (up || (y < (depth - 1) && level->isEmptyTile(x - 1, y + 1, z))) { // small edge texture t.vertexUV(x0, y1 + noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x1, y1 + noZFightingOffset, iz1, iu1, iv2); t.vertexUV(x1, y1 + noZFightingOffset, iz0, iu0, iv2); t.vertexUV(x0, y1 + noZFightingOffset, iz0, iu0, iv1); t.vertexUV(x1, y1 + noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x0, y1 + noZFightingOffset, iz1, iu1, iv2); t.vertexUV(x0, y1 + noZFightingOffset, iz0, iu0, iv2); t.vertexUV(x1, y1 + noZFightingOffset, iz0, iu0, iv1); } if (down || (y > 1 && level->isEmptyTile(x - 1, y - 1, z))) { // small edge texture t.vertexUV(x0, y0 - noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x1, y0 - noZFightingOffset, iz1, iu1, iv2); t.vertexUV(x1, y0 - noZFightingOffset, iz0, iu0, iv2); t.vertexUV(x0, y0 - noZFightingOffset, iz0, iu0, iv1); t.vertexUV(x1, y0 - noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x0, y0 - noZFightingOffset, iz1, iu1, iv2); t.vertexUV(x0, y0 - noZFightingOffset, iz0, iu0, iv2); t.vertexUV(x1, y0 - noZFightingOffset, iz0, iu0, iv1); } } else if (!w && e) { // half-step towards east t.vertexUV(x1, y1, z1, u1, v0); t.vertexUV(x1, y0, z1, u1, v2); t.vertexUV(x2, y0, z1, u2, v2); t.vertexUV(x2, y1, z1, u2, v0); t.vertexUV(x2, y1, z1, u1, v0); t.vertexUV(x2, y0, z1, u1, v2); t.vertexUV(x1, y0, z1, u2, v2); t.vertexUV(x1, y1, z1, u2, v0); // small edge texture if (!s && !n) { t.vertexUV(x1, y1, iz0, iu0, iv0); t.vertexUV(x1, y0, iz0, iu0, iv2); t.vertexUV(x1, y0, iz1, iu1, iv2); t.vertexUV(x1, y1, iz1, iu1, iv0); t.vertexUV(x1, y1, iz1, iu0, iv0); t.vertexUV(x1, y0, iz1, iu0, iv2); t.vertexUV(x1, y0, iz0, iu1, iv2); t.vertexUV(x1, y1, iz0, iu1, iv0); } if (up || (y < (depth - 1) && level->isEmptyTile(x + 1, y + 1, z))) { // small edge texture t.vertexUV(x1, y1 + noZFightingOffset, iz1, iu1, iv0); t.vertexUV(x2, y1 + noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x2, y1 + noZFightingOffset, iz0, iu0, iv1); t.vertexUV(x1, y1 + noZFightingOffset, iz0, iu0, iv0); t.vertexUV(x2, y1 + noZFightingOffset, iz1, iu1, iv0); t.vertexUV(x1, y1 + noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x1, y1 + noZFightingOffset, iz0, iu0, iv1); t.vertexUV(x2, y1 + noZFightingOffset, iz0, iu0, iv0); } if (down || (y > 1 && level->isEmptyTile(x + 1, y - 1, z))) { // small edge texture t.vertexUV(x1, y0 - noZFightingOffset, iz1, iu1, iv0); t.vertexUV(x2, y0 - noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x2, y0 - noZFightingOffset, iz0, iu0, iv1); t.vertexUV(x1, y0 - noZFightingOffset, iz0, iu0, iv0); t.vertexUV(x2, y0 - noZFightingOffset, iz1, iu1, iv0); t.vertexUV(x1, y0 - noZFightingOffset, iz1, iu1, iv1); t.vertexUV(x1, y0 - noZFightingOffset, iz0, iu0, iv1); t.vertexUV(x2, y0 - noZFightingOffset, iz0, iu0, iv0); } } if ((n && s) || (!w && !e && !n && !s)) { // straight north-south t.vertexUV(x1, y1, z2, u0, v0); t.vertexUV(x1, y0, z2, u0, v2); t.vertexUV(x1, y0, z0, u2, v2); t.vertexUV(x1, y1, z0, u2, v0); t.vertexUV(x1, y1, z0, u0, v0); t.vertexUV(x1, y0, z0, u0, v2); t.vertexUV(x1, y0, z2, u2, v2); t.vertexUV(x1, y1, z2, u2, v0); if (up) { // small edge texture t.vertexUV(ix1, y1, z2, iu1, iv2); t.vertexUV(ix1, y1, z0, iu1, iv0); t.vertexUV(ix0, y1, z0, iu0, iv0); t.vertexUV(ix0, y1, z2, iu0, iv2); t.vertexUV(ix1, y1, z0, iu1, iv2); t.vertexUV(ix1, y1, z2, iu1, iv0); t.vertexUV(ix0, y1, z2, iu0, iv0); t.vertexUV(ix0, y1, z0, iu0, iv2); } else { if (y < (depth - 1) && level->isEmptyTile(x, y + 1, z - 1)) { t.vertexUV(ix0, y1, z0, iu1, iv0); t.vertexUV(ix0, y1, z1, iu1, iv1); t.vertexUV(ix1, y1, z1, iu0, iv1); t.vertexUV(ix1, y1, z0, iu0, iv0); t.vertexUV(ix0, y1, z1, iu1, iv0); t.vertexUV(ix0, y1, z0, iu1, iv1); t.vertexUV(ix1, y1, z0, iu0, iv1); t.vertexUV(ix1, y1, z1, iu0, iv0); } if (y < (depth - 1) && level->isEmptyTile(x, y + 1, z + 1)) { t.vertexUV(ix0, y1, z1, iu0, iv1); t.vertexUV(ix0, y1, z2, iu0, iv2); t.vertexUV(ix1, y1, z2, iu1, iv2); t.vertexUV(ix1, y1, z1, iu1, iv1); t.vertexUV(ix0, y1, z2, iu0, iv1); t.vertexUV(ix0, y1, z1, iu0, iv2); t.vertexUV(ix1, y1, z1, iu1, iv2); t.vertexUV(ix1, y1, z2, iu1, iv1); } } if (down) { // small edge texture t.vertexUV(ix1, y0, z2, iu1, iv2); t.vertexUV(ix1, y0, z0, iu1, iv0); t.vertexUV(ix0, y0, z0, iu0, iv0); t.vertexUV(ix0, y0, z2, iu0, iv2); t.vertexUV(ix1, y0, z0, iu1, iv2); t.vertexUV(ix1, y0, z2, iu1, iv0); t.vertexUV(ix0, y0, z2, iu0, iv0); t.vertexUV(ix0, y0, z0, iu0, iv2); } else { if (y > 1 && level->isEmptyTile(x, y - 1, z - 1)) { // north half-step t.vertexUV(ix0, y0, z0, iu1, iv0); t.vertexUV(ix0, y0, z1, iu1, iv1); t.vertexUV(ix1, y0, z1, iu0, iv1); t.vertexUV(ix1, y0, z0, iu0, iv0); t.vertexUV(ix0, y0, z1, iu1, iv0); t.vertexUV(ix0, y0, z0, iu1, iv1); t.vertexUV(ix1, y0, z0, iu0, iv1); t.vertexUV(ix1, y0, z1, iu0, iv0); } if (y > 1 && level->isEmptyTile(x, y - 1, z + 1)) { // south half-step t.vertexUV(ix0, y0, z1, iu0, iv1); t.vertexUV(ix0, y0, z2, iu0, iv2); t.vertexUV(ix1, y0, z2, iu1, iv2); t.vertexUV(ix1, y0, z1, iu1, iv1); t.vertexUV(ix0, y0, z2, iu0, iv1); t.vertexUV(ix0, y0, z1, iu0, iv2); t.vertexUV(ix1, y0, z1, iu1, iv2); t.vertexUV(ix1, y0, z2, iu1, iv1); } } } else if (n && !s) { // half-step towards north t.vertexUV(x1, y1, z0, u0, v0); t.vertexUV(x1, y0, z0, u0, v2); t.vertexUV(x1, y0, z1, u1, v2); t.vertexUV(x1, y1, z1, u1, v0); t.vertexUV(x1, y1, z1, u0, v0); t.vertexUV(x1, y0, z1, u0, v2); t.vertexUV(x1, y0, z0, u1, v2); t.vertexUV(x1, y1, z0, u1, v0); // small edge texture if (!e && !w) { t.vertexUV(ix0, y1, z1, iu0, iv0); t.vertexUV(ix0, y0, z1, iu0, iv2); t.vertexUV(ix1, y0, z1, iu1, iv2); t.vertexUV(ix1, y1, z1, iu1, iv0); t.vertexUV(ix1, y1, z1, iu0, iv0); t.vertexUV(ix1, y0, z1, iu0, iv2); t.vertexUV(ix0, y0, z1, iu1, iv2); t.vertexUV(ix0, y1, z1, iu1, iv0); } if (up || (y < (depth - 1) && level->isEmptyTile(x, y + 1, z - 1))) { // small edge texture t.vertexUV(ix0, y1, z0, iu1, iv0); t.vertexUV(ix0, y1, z1, iu1, iv1); t.vertexUV(ix1, y1, z1, iu0, iv1); t.vertexUV(ix1, y1, z0, iu0, iv0); t.vertexUV(ix0, y1, z1, iu1, iv0); t.vertexUV(ix0, y1, z0, iu1, iv1); t.vertexUV(ix1, y1, z0, iu0, iv1); t.vertexUV(ix1, y1, z1, iu0, iv0); } if (down || (y > 1 && level->isEmptyTile(x, y - 1, z - 1))) { // small edge texture t.vertexUV(ix0, y0, z0, iu1, iv0); t.vertexUV(ix0, y0, z1, iu1, iv1); t.vertexUV(ix1, y0, z1, iu0, iv1); t.vertexUV(ix1, y0, z0, iu0, iv0); t.vertexUV(ix0, y0, z1, iu1, iv0); t.vertexUV(ix0, y0, z0, iu1, iv1); t.vertexUV(ix1, y0, z0, iu0, iv1); t.vertexUV(ix1, y0, z1, iu0, iv0); } } else if (!n && s) { // half-step towards south t.vertexUV(x1, y1, z1, u1, v0); t.vertexUV(x1, y0, z1, u1, v2); t.vertexUV(x1, y0, z2, u2, v2); t.vertexUV(x1, y1, z2, u2, v0); t.vertexUV(x1, y1, z2, u1, v0); t.vertexUV(x1, y0, z2, u1, v2); t.vertexUV(x1, y0, z1, u2, v2); t.vertexUV(x1, y1, z1, u2, v0); // small edge texture if (!e && !w) { t.vertexUV(ix1, y1, z1, iu0, iv0); t.vertexUV(ix1, y0, z1, iu0, iv2); t.vertexUV(ix0, y0, z1, iu1, iv2); t.vertexUV(ix0, y1, z1, iu1, iv0); t.vertexUV(ix0, y1, z1, iu0, iv0); t.vertexUV(ix0, y0, z1, iu0, iv2); t.vertexUV(ix1, y0, z1, iu1, iv2); t.vertexUV(ix1, y1, z1, iu1, iv0); } if (up || (y < (depth - 1) && level->isEmptyTile(x, y + 1, z + 1))) { // small edge texture t.vertexUV(ix0, y1, z1, iu0, iv1); t.vertexUV(ix0, y1, z2, iu0, iv2); t.vertexUV(ix1, y1, z2, iu1, iv2); t.vertexUV(ix1, y1, z1, iu1, iv1); t.vertexUV(ix0, y1, z2, iu0, iv1); t.vertexUV(ix0, y1, z1, iu0, iv2); t.vertexUV(ix1, y1, z1, iu1, iv2); t.vertexUV(ix1, y1, z2, iu1, iv1); } if (down || (y > 1 && level->isEmptyTile(x, y - 1, z + 1))) { // small edge texture t.vertexUV(ix0, y0, z1, iu0, iv1); t.vertexUV(ix0, y0, z2, iu0, iv2); t.vertexUV(ix1, y0, z2, iu1, iv2); t.vertexUV(ix1, y0, z1, iu1, iv1); t.vertexUV(ix0, y0, z2, iu0, iv1); t.vertexUV(ix0, y0, z1, iu0, iv2); t.vertexUV(ix1, y0, z1, iu1, iv2); t.vertexUV(ix1, y0, z2, iu1, iv1); } } return true; } void TileRenderer::tesselateRowTexture( Tile* tt, int data, float x, float y, float z ) { Tesselator& t = Tesselator::instance; int tex = tt->getTexture(0, data); if(fixedTexture >= 0) tex = fixedTexture; int xt = (tex & 0xf) << 4; int yt = tex & 0xf0; float u0 = (xt) / 256.0f; float u1 = (xt + 15.99f) / 256.f; float v0 = (yt) / 256.0f; float v1 = (yt + 15.99f) / 256.0f; float x0 = x + 0.5f - 0.25f; float x1 = x + 0.5f + 0.25f; float z0 = z + 0.5f - 0.5f; float z1 = z + 0.5f + 0.5f; t.vertexUV(x0, y + 1, z0, u0, v0); t.vertexUV(x0, y + 0, z0, u0, v1); t.vertexUV(x0, y + 0, z1, u1, v1); t.vertexUV(x0, y + 1, z1, u1, v0); t.vertexUV(x0, y + 1, z1, u0, v0); t.vertexUV(x0, y + 0, z1, u0, v1); t.vertexUV(x0, y + 0, z0, u1, v1); t.vertexUV(x0, y + 1, z0, u1, v0); t.vertexUV(x1, y + 1, z1, u0, v0); t.vertexUV(x1, y + 0, z1, u0, v1); t.vertexUV(x1, y + 0, z0, u1, v1); t.vertexUV(x1, y + 1, z0, u1, v0); t.vertexUV(x1, y + 1, z0, u0, v0); t.vertexUV(x1, y + 0, z0, u0, v1); t.vertexUV(x1, y + 0, z1, u1, v1); t.vertexUV(x1, y + 1, z1, u1, v0); x0 = x + 0.5f - 0.5f; x1 = x + 0.5f + 0.5f; z0 = z + 0.5f - 0.25f; z1 = z + 0.5f + 0.25f; t.vertexUV(x0, y + 1, z0, u0, v0); t.vertexUV(x0, y + 0, z0, u0, v1); t.vertexUV(x1, y + 0, z0, u1, v1); t.vertexUV(x1, y + 1, z0, u1, v0); t.vertexUV(x1, y + 1, z0, u0, v0); t.vertexUV(x1, y + 0, z0, u0, v1); t.vertexUV(x0, y + 0, z0, u1, v1); t.vertexUV(x0, y + 1, z0, u1, v0); t.vertexUV(x1, y + 1, z1, u0, v0); t.vertexUV(x1, y + 0, z1, u0, v1); t.vertexUV(x0, y + 0, z1, u1, v1); t.vertexUV(x0, y + 1, z1, u1, v0); t.vertexUV(x0, y + 1, z1, u0, v0); t.vertexUV(x0, y + 0, z1, u0, v1); t.vertexUV(x1, y + 0, z1, u1, v1); t.vertexUV(x1, y + 1, z1, u1, v0); }