fix(adt): scrub NaN/inf in MDDF + MODF placement floats

ADT placement positions and rotations are loaded as raw floats from the
binary chunks. A corrupted MDDF/MODF entry could feed NaN into the
M2/WMO instance transform and crash render. Now position/rotation are
scrubbed for both MDDF doodads and MODF buildings; MODF also scrubs the
extentLower/extentUpper bounding box used for cull tests.
This commit is contained in:
Kelsi 2026-05-06 06:05:17 -07:00
parent 15bf77c616
commit 5b6f59bbbd

View file

@ -216,6 +216,12 @@ void ADTLoader::parseMDDF(const uint8_t* data, size_t size, ADTTerrain& terrain)
placement.rotation[2] = readFloat(data, offset + 28);
placement.scale = readUInt16(data, offset + 32);
placement.flags = readUInt16(data, offset + 34);
// Sanitize NaN/inf — corrupted MDDF entries would propagate bad
// floats into the WMO/M2 instance transform and crash render.
for (int k = 0; k < 3; k++) {
if (!std::isfinite(placement.position[k])) placement.position[k] = 0.0f;
if (!std::isfinite(placement.rotation[k])) placement.rotation[k] = 0.0f;
}
terrain.doodadPlacements.push_back(placement);
}
@ -255,6 +261,14 @@ void ADTLoader::parseMODF(const uint8_t* data, size_t size, ADTTerrain& terrain)
placement.scale = readUInt16(data, offset + 62);
if (placement.scale == 0) placement.scale = 1024;
}
// Same NaN scrub as MDDF entries — corrupted MODF would crash WMO
// instance transform.
for (int k = 0; k < 3; k++) {
if (!std::isfinite(placement.position[k])) placement.position[k] = 0.0f;
if (!std::isfinite(placement.rotation[k])) placement.rotation[k] = 0.0f;
if (!std::isfinite(placement.extentLower[k])) placement.extentLower[k] = 0.0f;
if (!std::isfinite(placement.extentUpper[k])) placement.extentUpper[k] = 0.0f;
}
terrain.wmoPlacements.push_back(placement);
}