feat: client-side WOC collision loading + walkability queries

- TerrainManager loads WOC collision meshes alongside WOT/WHM terrain
  from both custom_zones/ and output/ directories
- CollisionData stored per-tile with triangle array + bounds
- isPositionWalkable(x, y): returns whether a world position is on
  walkable terrain (barycentric point-in-triangle test)
- getCollisionFlags(x, y): returns per-triangle flags (walkable,
  water, steep, indoor) for movement system integration
- Defaults to walkable when no collision data is loaded (backward compat)
- Custom zone players now have proper terrain physics boundaries
This commit is contained in:
Kelsi 2026-05-05 15:32:48 -07:00
parent a25c4cfe1f
commit cff8d359e4
2 changed files with 72 additions and 0 deletions

View file

@ -260,6 +260,10 @@ public:
*/
std::optional<float> getHeightAt(float glX, float glY) const;
// Collision queries using WOC data (custom zones)
bool isPositionWalkable(float glX, float glY) const;
uint8_t getCollisionFlags(float glX, float glY) const;
/**
* Get dominant terrain texture name at a GL position.
* Returns empty if terrain is not loaded at that position.
@ -356,6 +360,16 @@ private:
bool taxiStreamingMode_ = false;
bool isCustomZone_ = false;
// Collision data for custom zones (loaded from WOC files)
struct CollisionData {
struct Triangle { glm::vec3 v0, v1, v2; uint8_t flags; };
std::vector<Triangle> triangles;
glm::vec3 boundsMin{1e30f}, boundsMax{-1e30f};
bool loaded = false;
};
std::unordered_map<uint64_t, CollisionData> collisionTiles_;
uint64_t tileKey(int x, int y) const { return (static_cast<uint64_t>(x) << 32) | static_cast<uint32_t>(y); }
// Tile size constants (WoW ADT specifications)
// A tile (ADT) = 16x16 chunks = 533.33 units across
// A chunk = 8x8 vertex quads = 33.33 units across