refactor: name ADT vertex constants, add BLP decompression comments

- adt_loader: replace magic 145 with kMCVTVertexCount and 17 with
  kMCVTRowStride — MCVT height grid is 9 outer + 8 inner vertices
  per row across 9 rows
- adt_loader: replace 999999.0f sentinels with numeric_limits
- blp_loader: add why-comments on RGB565→RGB888 bit layout
  (R=bits[15:11], G=[10:5], B=[4:0])
- blp_loader: explain DXT3 4-bit alpha scaling (n * 255 / 15)
- blp_loader: explain palette 4-bit alpha multiply-by-17 trick
  (equivalent to n * 255 / 15, exact for all 16 values)
This commit is contained in:
Kelsi 2026-03-30 14:28:22 -07:00
parent 683e171fd1
commit 1151785381
2 changed files with 21 additions and 18 deletions

View file

@ -3,23 +3,25 @@
#include <cstring>
#include <cmath>
#include <algorithm>
#include <limits>
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<float>::max();
float maxHeight = std::numeric_limits<float>::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<int8_t>(data[i]);
}
}

View file

@ -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) {