refactor: name random/camera constants, add alpha map static_assert

- terrain_manager: extract kRand16Max (65535.0f) from 8 duplicated
  random normalization expressions — 16-bit mask to [0..1] float
- terrain_manager: add static_assert verifying packed alpha unpacks
  to full alpha map size (ALPHA_MAP_PACKED * 2 == ALPHA_MAP_SIZE)
- camera_controller: name kCameraClipEpsilon (0.1f) with why-comment
  preventing character model clipping at near-minimum distance
This commit is contained in:
Kelsi 2026-03-30 15:17:37 -07:00
parent a389fd2ef4
commit 55cac39541
2 changed files with 17 additions and 10 deletions

View file

@ -191,8 +191,11 @@ void CameraController::update(float deltaTime) {
// Compute camera position // Compute camera position
glm::vec3 actualCam; glm::vec3 actualCam;
if (actualDist < MIN_DISTANCE + 0.1f) { // Small offset prevents the camera from clipping into the character
actualCam = pivot + forward3D * 0.1f; // model when collision pushes it to near-minimum distance.
constexpr float kCameraClipEpsilon = 0.1f;
if (actualDist < MIN_DISTANCE + kCameraClipEpsilon) {
actualCam = pivot + forward3D * kCameraClipEpsilon;
} else { } else {
actualCam = pivot + camDir * actualDist; actualCam = pivot + camDir * actualDist;
} }

View file

@ -45,9 +45,13 @@ namespace {
// Alpha map format constants // Alpha map format constants
constexpr size_t ALPHA_MAP_SIZE = 4096; // 64×64 uncompressed alpha bytes constexpr size_t ALPHA_MAP_SIZE = 4096; // 64×64 uncompressed alpha bytes
constexpr size_t ALPHA_MAP_PACKED = 2048; // 64×64 packed 4-bit alpha (half size) constexpr size_t ALPHA_MAP_PACKED = 2048; // 64×64 packed 4-bit alpha (half size)
static_assert(ALPHA_MAP_PACKED * 2 == ALPHA_MAP_SIZE, "packed alpha must unpack to full size");
constexpr uint8_t ALPHA_FILL_FLAG = 0x80; // RLE command: fill vs. copy constexpr uint8_t ALPHA_FILL_FLAG = 0x80; // RLE command: fill vs. copy
constexpr uint8_t ALPHA_COUNT_MASK = 0x7F; // RLE command: count bits constexpr uint8_t ALPHA_COUNT_MASK = 0x7F; // RLE command: count bits
// Random float normalization: mask to 16-bit then divide by max value to get [0..1]
constexpr float kRand16Max = 65535.0f;
// Placement transform constants // Placement transform constants
constexpr float kDegToRad = 3.14159f / 180.0f; constexpr float kDegToRad = 3.14159f / 180.0f;
constexpr float kInv1024 = 1.0f / 1024.0f; constexpr float kInv1024 = 1.0f / 1024.0f;
@ -1897,8 +1901,8 @@ void TerrainManager::generateGroundClutterPlacements(std::shared_ptr<PendingTile
}; };
for (uint32_t a = 0; a < attempts; ++a) { for (uint32_t a = 0; a < attempts; ++a) {
float fracX = (nextRand() & 0xFFFFu) / 65535.0f * 8.0f; float fracX = (nextRand() & 0xFFFFu) / kRand16Max * 8.0f;
float fracY = (nextRand() & 0xFFFFu) / 65535.0f * 8.0f; float fracY = (nextRand() & 0xFFFFu) / kRand16Max * 8.0f;
if (hasAlpha && !alphaScratch.empty()) { if (hasAlpha && !alphaScratch.empty()) {
int alphaX = glm::clamp(static_cast<int>((fracX / 8.0f) * 63.0f), 0, 63); int alphaX = glm::clamp(static_cast<int>((fracX / 8.0f) * 63.0f), 0, 63);
@ -1965,8 +1969,8 @@ void TerrainManager::generateGroundClutterPlacements(std::shared_ptr<PendingTile
p.uniqueId = 0; p.uniqueId = 0;
// MCNK chunk.position is already in terrain/render world space. // MCNK chunk.position is already in terrain/render world space.
// Do not convert via ADT placement mapping (that is for MDDF/MODF records). // Do not convert via ADT placement mapping (that is for MDDF/MODF records).
p.rotation = glm::vec3(0.0f, 0.0f, (nextRand() & 0xFFFFu) / 65535.0f * (2.0f * pi)); p.rotation = glm::vec3(0.0f, 0.0f, (nextRand() & 0xFFFFu) / kRand16Max * (2.0f * pi));
p.scale = 0.80f + ((nextRand() & 0xFFFFu) / 65535.0f) * 0.35f; p.scale = 0.80f + ((nextRand() & 0xFFFFu) / kRand16Max) * 0.35f;
// Snap directly to sampled terrain height. // Snap directly to sampled terrain height.
p.position = glm::vec3(worldX, worldY, worldZ + 0.01f); p.position = glm::vec3(worldX, worldY, worldZ + 0.01f);
pending->m2Placements.push_back(p); pending->m2Placements.push_back(p);
@ -2005,8 +2009,8 @@ void TerrainManager::generateGroundClutterPlacements(std::shared_ptr<PendingTile
return seed; return seed;
}; };
float fracX = (nextRand() & 0xFFFFu) / 65535.0f * 8.0f; float fracX = (nextRand() & 0xFFFFu) / kRand16Max * 8.0f;
float fracY = (nextRand() & 0xFFFFu) / 65535.0f * 8.0f; float fracY = (nextRand() & 0xFFFFu) / kRand16Max * 8.0f;
if (hasRoadLikeTextureAt(chunk, fracX, fracY)) { if (hasRoadLikeTextureAt(chunk, fracX, fracY)) {
roadRejected++; roadRejected++;
continue; continue;
@ -2033,8 +2037,8 @@ void TerrainManager::generateGroundClutterPlacements(std::shared_ptr<PendingTile
PendingTile::M2Placement p; PendingTile::M2Placement p;
p.modelId = proxyModelId; p.modelId = proxyModelId;
p.uniqueId = 0; p.uniqueId = 0;
p.rotation = glm::vec3(0.0f, 0.0f, (nextRand() & 0xFFFFu) / 65535.0f * (2.0f * pi)); p.rotation = glm::vec3(0.0f, 0.0f, (nextRand() & 0xFFFFu) / kRand16Max * (2.0f * pi));
p.scale = 0.75f + ((nextRand() & 0xFFFFu) / 65535.0f) * 0.40f; p.scale = 0.75f + ((nextRand() & 0xFFFFu) / kRand16Max) * 0.40f;
p.position = glm::vec3(worldX, worldY, worldZ + 0.01f); p.position = glm::vec3(worldX, worldY, worldZ + 0.01f);
pending->m2Placements.push_back(p); pending->m2Placements.push_back(p);
fallbackAdded++; fallbackAdded++;