mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Filter WMO decorative geometry from collision, fix tram portal trigger IDs
Parse MOPY per-triangle flags in WMO groups and exclude detail/decorative triangles (flag 0x04) from collision detection. This prevents invisible walls from objects like gears and railings in WMO interiors. Add WotLK area trigger IDs 2173/2175 to extended-range tram triggers.
This commit is contained in:
parent
cefb05c027
commit
ee4e6a31ce
4 changed files with 30 additions and 3 deletions
|
|
@ -157,6 +157,7 @@ struct WMOGroup {
|
||||||
std::vector<WMOVertex> vertices;
|
std::vector<WMOVertex> vertices;
|
||||||
std::vector<uint16_t> indices;
|
std::vector<uint16_t> indices;
|
||||||
std::vector<WMOBatch> batches;
|
std::vector<WMOBatch> batches;
|
||||||
|
std::vector<uint8_t> triFlags; // Per-triangle MOPY flags (0x04 = detail/no-collide)
|
||||||
|
|
||||||
// Portals
|
// Portals
|
||||||
std::vector<WMOPortal> portals;
|
std::vector<WMOPortal> portals;
|
||||||
|
|
|
||||||
|
|
@ -8812,8 +8812,9 @@ void GameHandler::checkAreaTriggers() {
|
||||||
// Deeprun Tram entrance triggers need extended range because WMO
|
// Deeprun Tram entrance triggers need extended range because WMO
|
||||||
// collision walls block the player from reaching the trigger center.
|
// collision walls block the player from reaching the trigger center.
|
||||||
static const std::unordered_set<uint32_t> extendedRangeTriggers = {
|
static const std::unordered_set<uint32_t> extendedRangeTriggers = {
|
||||||
712, 713, // Stormwind/Ironforge → Deeprun Tram
|
712, 713, // Stormwind/Ironforge → Deeprun Tram (classic IDs)
|
||||||
2166, 2171, // Tram interior exit triggers
|
2166, 2171, // Tram interior exit triggers
|
||||||
|
2173, 2175, // Stormwind/Ironforge tram entrance (WotLK IDs)
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto& at : areaTriggers_) {
|
for (const auto& at : areaTriggers_) {
|
||||||
|
|
|
||||||
|
|
@ -498,6 +498,16 @@ bool WMOLoader::loadGroup(const std::vector<uint8_t>& groupData,
|
||||||
group.indices.push_back(read<uint16_t>(groupData, mogpOffset));
|
group.indices.push_back(read<uint16_t>(groupData, mogpOffset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (subChunkId == 0x4D4F5059) { // MOPY - Triangle material info
|
||||||
|
// 2 bytes per triangle: flags (uint8) + materialId (uint8)
|
||||||
|
// flag 0x04 = detail/decorative geometry (no collision)
|
||||||
|
uint32_t triCount = subChunkSize / 2;
|
||||||
|
group.triFlags.resize(triCount);
|
||||||
|
for (uint32_t i = 0; i < triCount; i++) {
|
||||||
|
group.triFlags[i] = read<uint8_t>(groupData, mogpOffset);
|
||||||
|
read<uint8_t>(groupData, mogpOffset); // materialId (skip)
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (subChunkId == 0x4D4F4E52) { // MONR - Normals
|
else if (subChunkId == 0x4D4F4E52) { // MONR - Normals
|
||||||
uint32_t normalCount = subChunkSize / 12;
|
uint32_t normalCount = subChunkSize / 12;
|
||||||
core::Logger::getInstance().debug(" MONR: ", normalCount, " normals for ", group.vertices.size(), " vertices");
|
core::Logger::getInstance().debug(" MONR: ", normalCount, " normals for ", group.vertices.size(), " vertices");
|
||||||
|
|
|
||||||
|
|
@ -1871,12 +1871,27 @@ bool WMORenderer::createGroupResources(const pipeline::WMOGroup& group, GroupRes
|
||||||
resources.indexBuffer = idxBuf.buffer;
|
resources.indexBuffer = idxBuf.buffer;
|
||||||
resources.indexAlloc = idxBuf.allocation;
|
resources.indexAlloc = idxBuf.allocation;
|
||||||
|
|
||||||
// Store collision geometry for floor raycasting
|
// Store collision geometry for floor raycasting.
|
||||||
|
// Use MOPY per-triangle flags to exclude detail/decorative geometry (flag 0x04)
|
||||||
|
// from collision — these are things like gears, railings, etc.
|
||||||
resources.collisionVertices.reserve(group.vertices.size());
|
resources.collisionVertices.reserve(group.vertices.size());
|
||||||
for (const auto& v : group.vertices) {
|
for (const auto& v : group.vertices) {
|
||||||
resources.collisionVertices.push_back(v.position);
|
resources.collisionVertices.push_back(v.position);
|
||||||
}
|
}
|
||||||
resources.collisionIndices = group.indices;
|
if (!group.triFlags.empty()) {
|
||||||
|
// Filter out non-collidable triangles
|
||||||
|
resources.collisionIndices.reserve(group.indices.size());
|
||||||
|
size_t numTris = group.indices.size() / 3;
|
||||||
|
for (size_t t = 0; t < numTris; t++) {
|
||||||
|
uint8_t flags = (t < group.triFlags.size()) ? group.triFlags[t] : 0;
|
||||||
|
if (flags & 0x04) continue; // detail/decorative — skip collision
|
||||||
|
resources.collisionIndices.push_back(group.indices[t * 3 + 0]);
|
||||||
|
resources.collisionIndices.push_back(group.indices[t * 3 + 1]);
|
||||||
|
resources.collisionIndices.push_back(group.indices[t * 3 + 2]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resources.collisionIndices = group.indices;
|
||||||
|
}
|
||||||
|
|
||||||
// Compute actual bounding box from vertices (WMO header bboxes can be unreliable)
|
// Compute actual bounding box from vertices (WMO header bboxes can be unreliable)
|
||||||
if (!resources.collisionVertices.empty()) {
|
if (!resources.collisionVertices.empty()) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue