From 45048757ef02790b2e48c31b33a78964608aa117 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Thu, 5 Feb 2026 23:26:30 -0800 Subject: [PATCH] Fix geoset filtering using correct geosetId from M2 batch M2 batches have a geosetIndex field that determines the geoset group for filtering (0-18=body, 1xx=hair, etc.). We were incorrectly using submeshId from the submesh struct instead. Now properly stores and uses geosetId. --- include/pipeline/m2_loader.hpp | 5 +++-- src/pipeline/m2_loader.cpp | 1 + src/rendering/character_renderer.cpp | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/pipeline/m2_loader.hpp b/include/pipeline/m2_loader.hpp index f13db470..e66a3200 100644 --- a/include/pipeline/m2_loader.hpp +++ b/include/pipeline/m2_loader.hpp @@ -104,9 +104,10 @@ struct M2Batch { uint32_t vertexStart; // First vertex uint32_t vertexCount; // Number of vertices - // Geoset info (from submesh) - uint16_t submeshId = 0; // Submesh/geoset ID (determines body part group) + // Geoset info + uint16_t submeshId = 0; // Submesh ID from skin file uint16_t submeshLevel = 0; // Submesh level (0=base, 1+=LOD/alternate mesh) + uint16_t geosetId = 0; // Geoset ID for filtering (0-18=body, 1xx=hair, etc.) }; // Attachment point (bone-anchored position for weapons, effects, etc.) diff --git a/src/pipeline/m2_loader.cpp b/src/pipeline/m2_loader.cpp index 52b77c83..014fd6bc 100644 --- a/src/pipeline/m2_loader.cpp +++ b/src/pipeline/m2_loader.cpp @@ -627,6 +627,7 @@ bool M2Loader::loadSkin(const std::vector& skinData, M2Model& model) { batch.textureUnit = db.textureCoordIndex; batch.transparencyIndex = db.textureWeightIndex; batch.textureAnimIndex = db.textureTransformIndex; + batch.geosetId = db.geosetIndex; // Geoset ID for filtering (from batch, not submesh) // Look up proper vertex/index ranges from submesh if (db.skinSectionIndex < submeshes.size()) { diff --git a/src/rendering/character_renderer.cpp b/src/rendering/character_renderer.cpp index 96b854f5..77568b5a 100644 --- a/src/rendering/character_renderer.cpp +++ b/src/rendering/character_renderer.cpp @@ -1179,7 +1179,7 @@ void CharacterRenderer::render(const Camera& camera, const glm::mat4& view, cons int rendered = 0, skipped = 0; for (const auto& b : gpuModel.data.batches) { bool filtered = !instance.activeGeosets.empty() && - instance.activeGeosets.find(b.submeshId) == instance.activeGeosets.end(); + instance.activeGeosets.find(b.geosetId) == instance.activeGeosets.end(); GLuint resolvedTex = whiteTexture; std::string texInfo = "white(fallback)"; @@ -1219,7 +1219,7 @@ void CharacterRenderer::render(const Camera& camera, const glm::mat4& view, cons for (const auto& batch : gpuModel.data.batches) { // Filter by active geosets (if set) if (!instance.activeGeosets.empty() && - instance.activeGeosets.find(batch.submeshId) == instance.activeGeosets.end()) { + instance.activeGeosets.find(batch.geosetId) == instance.activeGeosets.end()) { continue; }