diff --git a/src/pipeline/adt_loader.cpp b/src/pipeline/adt_loader.cpp index 3fd84f79..c629606b 100644 --- a/src/pipeline/adt_loader.cpp +++ b/src/pipeline/adt_loader.cpp @@ -3,23 +3,25 @@ #include #include #include +#include namespace wowee { namespace pipeline { +// MCVT height grid: 9 outer + 8 inner vertices per row, 9 rows = 145 total. +// Each row is 17 entries: 9 outer corner vertices then 8 inner midpoints. +static constexpr int kMCVTVertexCount = 145; +static constexpr int kMCVTRowStride = 17; // 9 outer + 8 inner per row + // HeightMap implementation float HeightMap::getHeight(int x, int y) const { if (x < 0 || x > 8 || y < 0 || y > 8) { return 0.0f; } - // MCVT heights are stored in interleaved 9x17 row-major layout: - // Row 0: 9 outer (indices 0-8), then 8 inner (indices 9-16) - // Row 1: 9 outer (indices 17-25), then 8 inner (indices 26-33) - // ... - // Outer vertex (x, y) is at index: y * 17 + x - int index = y * 17 + x; - if (index < 0 || index >= 145) return 0.0f; + // Outer vertex (x, y) in the interleaved grid + int index = y * kMCVTRowStride + x; + if (index < 0 || index >= kMCVTVertexCount) return 0.0f; return heights[index]; } @@ -355,16 +357,15 @@ void ADTLoader::parseMCNK(const uint8_t* data, size_t size, int chunkIndex, ADTT } void ADTLoader::parseMCVT(const uint8_t* data, size_t size, MapChunk& chunk) { - // MCVT contains 145 height values (floats) - if (size < 145 * sizeof(float)) { + if (size < kMCVTVertexCount * sizeof(float)) { LOG_WARNING("MCVT chunk too small: ", size, " bytes"); return; } - float minHeight = 999999.0f; - float maxHeight = -999999.0f; + float minHeight = std::numeric_limits::max(); + float maxHeight = std::numeric_limits::lowest(); - for (int i = 0; i < 145; i++) { + for (int i = 0; i < kMCVTVertexCount; i++) { float height = readFloat(data, i * sizeof(float)); chunk.heightMap.heights[i] = height; @@ -386,13 +387,13 @@ void ADTLoader::parseMCVT(const uint8_t* data, size_t size, MapChunk& chunk) { } void ADTLoader::parseMCNR(const uint8_t* data, size_t size, MapChunk& chunk) { - // MCNR contains 145 normals (3 bytes each, signed) - if (size < 145 * 3) { + // MCNR: one signed XYZ normal per vertex (3 bytes each) + if (size < kMCVTVertexCount * 3) { LOG_WARNING("MCNR chunk too small: ", size, " bytes"); return; } - for (int i = 0; i < 145 * 3; i++) { + for (int i = 0; i < kMCVTVertexCount * 3; i++) { chunk.normals[i] = static_cast(data[i]); } } diff --git a/src/pipeline/blp_loader.cpp b/src/pipeline/blp_loader.cpp index e83cd84a..02281dbe 100644 --- a/src/pipeline/blp_loader.cpp +++ b/src/pipeline/blp_loader.cpp @@ -209,7 +209,8 @@ void BLPLoader::decompressDXT1(const uint8_t* src, uint8_t* dst, int width, int uint16_t c0 = block[0] | (block[1] << 8); uint16_t c1 = block[2] | (block[3] << 8); - // Convert RGB565 to RGB888 + // Convert RGB565 to RGB888: extract 5/6/5-bit channels and scale to [0..255]. + // R = bits[15:11] (5-bit, /31), G = bits[10:5] (6-bit, /63), B = bits[4:0] (5-bit, /31) uint8_t r0 = ((c0 >> 11) & 0x1F) * 255 / 31; uint8_t g0 = ((c0 >> 5) & 0x3F) * 255 / 63; uint8_t b0 = (c0 & 0x1F) * 255 / 31; @@ -303,7 +304,7 @@ void BLPLoader::decompressDXT3(const uint8_t* src, uint8_t* dst, int width, int case 3: pixel[0] = (r0 + 2*r1) / 3; pixel[1] = (g0 + 2*g1) / 3; pixel[2] = (b0 + 2*b1) / 3; break; } - // Apply 4-bit alpha + // Apply 4-bit alpha: scale [0..15] → [0..255] via (n * 255 / 15) int alphaIndex = py * 4 + px; uint8_t alpha4 = (alphaBlock >> (alphaIndex * 4)) & 0xF; pixel[3] = alpha4 * 255 / 15; @@ -416,7 +417,8 @@ void BLPLoader::decompressPalette(const uint8_t* src, uint8_t* dst, const uint32 if (alphaDepth == 8) { dst[i * 4 + 3] = alphaData[i]; } else if (alphaDepth == 4) { - // 4-bit alpha: 2 pixels per byte + // 4-bit alpha: 2 pixels packed per byte (low nibble first). + // Multiply by 17 to scale [0..15] → [0..255] (equivalent to n * 255 / 15). uint8_t alphaByte = alphaData[i / 2]; dst[i * 4 + 3] = (i % 2 == 0) ? ((alphaByte & 0x0F) * 17) : ((alphaByte >> 4) * 17); } else if (alphaDepth == 1) {