feat: render equipment on other players (helmets, weapons, belts, wrists)

Other players previously appeared partially naked — only chest, legs, feet,
hands, cape, and tabard rendered. Now renders full equipment:

- Helmet M2 model: loads from ItemDisplayInfo.dbc with race/gender suffix,
  attaches at head bone (point 0/11), hides hair geoset under helm
- Weapons: mainhand (attachment 1) and offhand (attachment 2) M2 models
  loaded from ItemDisplayInfo, with Weapon/Shield path fallback
- Wrist/bracer geoset (group 8): applies when no chest sleeve overrides
- Belt/waist geoset (group 18): reads GeosetGroup1 from ItemDisplayInfo
- Shoulder M2 attachments deferred (separate bone attachment system)

Also applied same wrist/waist geosets to NPC and character preview paths.

Minimap: batch 9 individual vkUpdateDescriptorSets into single call.
This commit is contained in:
Kelsi 2026-03-27 17:30:35 -07:00
parent 50a3eb7f07
commit 0396a42beb
3 changed files with 223 additions and 10 deletions

View file

@ -11,6 +11,7 @@
#include "core/coordinates.hpp"
#include "core/logger.hpp"
#include <glm/gtc/matrix_transform.hpp>
#include <array>
#include <sstream>
#include <cmath>
@ -380,7 +381,10 @@ VkTexture* Minimap::getOrLoadTileTexture(int tileX, int tileY) {
// --------------------------------------------------------
void Minimap::updateTileDescriptors(uint32_t frameIdx, int centerTileX, int centerTileY) {
constexpr int kTileCount = 9; // 3x3 grid
VkDevice device = vkCtx->getDevice();
std::array<VkDescriptorImageInfo, kTileCount> imgInfos{};
std::array<VkWriteDescriptorSet, kTileCount> writes{};
int slot = 0;
for (int dr = -1; dr <= 1; dr++) {
@ -392,20 +396,20 @@ void Minimap::updateTileDescriptors(uint32_t frameIdx, int centerTileX, int cent
if (!tileTex || !tileTex->isValid())
tileTex = noDataTexture.get();
VkDescriptorImageInfo imgInfo = tileTex->descriptorInfo();
imgInfos[slot] = tileTex->descriptorInfo();
VkWriteDescriptorSet write{};
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write.dstSet = tileDescSets[frameIdx][slot];
write.dstBinding = 0;
write.descriptorCount = 1;
write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
write.pImageInfo = &imgInfo;
vkUpdateDescriptorSets(device, 1, &write, 0, nullptr);
writes[slot] = {};
writes[slot].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writes[slot].dstSet = tileDescSets[frameIdx][slot];
writes[slot].dstBinding = 0;
writes[slot].descriptorCount = 1;
writes[slot].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
writes[slot].pImageInfo = &imgInfos[slot];
slot++;
}
}
vkUpdateDescriptorSets(device, kTileCount, writes.data(), 0, nullptr);
}
// --------------------------------------------------------