From 4bb20e560f82943071216c2db90134a08ab8eaa4 Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 21 Jul 2026 21:10:15 +0100 Subject: [PATCH] fix: skin uv inset (#6803) --- .../skin-rendering/use-ears-mod-features.ts | 2 +- packages/ui/src/utils/webgl/skin-rendering.ts | 48 ------------------- 2 files changed, 1 insertion(+), 49 deletions(-) diff --git a/packages/ui/src/composables/skin-rendering/use-ears-mod-features.ts b/packages/ui/src/composables/skin-rendering/use-ears-mod-features.ts index 413efe1248..5feb30018c 100644 --- a/packages/ui/src/composables/skin-rendering/use-ears-mod-features.ts +++ b/packages/ui/src/composables/skin-rendering/use-ears-mod-features.ts @@ -131,7 +131,7 @@ const SKIN_SIZE = 64 const EARS_V0_MAGIC = 0x3f23d8 const EARS_V1_MAGIC = 0xea2501 const ALFALFA_MAGIC = 0xea1fa1fa -const UV_TEXEL_INSET = 0.5 +const UV_TEXEL_INSET = 1 / 32 const EAR_MODES: EarMode[] = [ 'NONE', diff --git a/packages/ui/src/utils/webgl/skin-rendering.ts b/packages/ui/src/utils/webgl/skin-rendering.ts index 93a2e9e05e..9505f6e00f 100644 --- a/packages/ui/src/utils/webgl/skin-rendering.ts +++ b/packages/ui/src/utils/webgl/skin-rendering.ts @@ -13,8 +13,6 @@ const modelCache: Map = new Map() const modelPromiseCache: Map> = new Map() const textureCache: Map = new Map() const texturePromiseCache: Map> = new Map() -const SKIN_TEXTURE_SIZE = 64 -const SKIN_UV_INSET_VERSION = 1 export async function loadModel(modelUrl: string): Promise { if (modelCache.has(modelUrl)) { @@ -155,58 +153,12 @@ function setCommonMaterialProperties(mat: THREE.MeshStandardMaterial): void { } } -function insetSkinGeometryUvs(geometry: THREE.BufferGeometry): void { - if (geometry.userData.skinUvInsetVersion === SKIN_UV_INSET_VERSION) return - - const uv = geometry.getAttribute('uv') - if (!uv || uv.itemSize < 2 || uv.count % 4 !== 0) return - - for (let faceStart = 0; faceStart < uv.count; faceStart += 4) { - let minU = Infinity - let maxU = -Infinity - let minV = Infinity - let maxV = -Infinity - - for (let vertex = faceStart; vertex < faceStart + 4; vertex++) { - const u = uv.getX(vertex) - const v = uv.getY(vertex) - minU = Math.min(minU, u) - maxU = Math.max(maxU, u) - minV = Math.min(minV, v) - maxV = Math.max(maxV, v) - } - - const insetMinU = (Math.round(minU * SKIN_TEXTURE_SIZE) + 0.5) / SKIN_TEXTURE_SIZE - const insetMaxU = (Math.round(maxU * SKIN_TEXTURE_SIZE) - 0.5) / SKIN_TEXTURE_SIZE - const insetMinV = (Math.round(minV * SKIN_TEXTURE_SIZE) + 0.5) / SKIN_TEXTURE_SIZE - const insetMaxV = (Math.round(maxV * SKIN_TEXTURE_SIZE) - 0.5) / SKIN_TEXTURE_SIZE - - for (let vertex = faceStart; vertex < faceStart + 4; vertex++) { - const u = uv.getX(vertex) - const v = uv.getY(vertex) - const insetU = u === minU ? insetMinU : u === maxU ? insetMaxU : u - const insetV = v === minV ? insetMinV : v === maxV ? insetMaxV : v - uv.setXY(vertex, insetU, insetV) - } - } - - uv.needsUpdate = true - geometry.userData.skinUvInsetVersion = SKIN_UV_INSET_VERSION -} - export function applyTexture(model: THREE.Object3D, texture: THREE.Texture): void { model.traverse((child) => { if ((child as THREE.Mesh).isMesh) { const mesh = child as THREE.Mesh const isSkinLayer = mesh.name.endsWith('_Layer') const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material] - const usesSkinTexture = materials.some( - (mat) => mat instanceof THREE.MeshStandardMaterial && mat.name !== 'cape', - ) - - if (usesSkinTexture) { - insetSkinGeometryUvs(mesh.geometry) - } materials.forEach((mat: THREE.Material) => { if (mat instanceof THREE.MeshStandardMaterial) {