fix render

This commit is contained in:
Rodrigo Bertoldo de Sousa Martins committed 2026-09-11 16:05:12 -03:00
1 parent bfa4552f24
commit 57a8a5fe50
1 file changed
+100
+100
View File
@@ -175,6 +175,105 @@ function isLeaderLinePointCloud(points) {
return p90 < axisLen * 0.1;
}
// Cobre um caso que isLeaderLineMesh() sozinho não pega: quando a linha de
// chamada NÃO é um nó separado, e sim geometria extra soldada dentro do
// MESMO primitivo de uma estrutura real (ex: a malha de uma região da pele
// vem com um "espinho" fino grudado nela desde a exportação do FBX
// original). Como a maior parte da malha nesse caso é a estrutura de
// verdade (não uma linha), o teste de colinearidade da malha INTEIRA
// reprova, e o espinho sobrevive grudado — foi exatamente o que apareceu
// como tracinhos saindo do corpo (cabeça, mão, canela) mesmo depois do
// filtro por malha. A correção certa é olhar por PEDAÇO CONECTADO da
// malha (componentes que não compartilham nenhum vértice entre si), não a
// malha toda: cada pedaço geometricamente desconectado é testado
// separadamente, e só os que passam no teste de "reto e fino" são
// removidos — a estrutura real (um componente só, com volume) nunca é.
function stripLeaderLineComponents(mesh) {
try {
stripLeaderLineComponentsUnsafe(mesh);
} catch {
// Nunca deixa uma malha atípica derrubar o pipeline inteiro — na
// dúvida, mantém a estrutura como veio (mesmo comportamento de antes
// desta função existir).
}
}
function stripLeaderLineComponentsUnsafe(mesh) {
for (const prim of mesh.listPrimitives()) {
const posAccessor = prim.getAttribute("POSITION");
const indicesAccessor = prim.getIndices();
if (!posAccessor || !indicesAccessor) continue;
const indices = indicesAccessor.getArray();
const posArr = posAccessor.getArray();
if (!indices || !posArr || indices.length < 3) continue;
const at = (vi) => [posArr[vi * 3], posArr[vi * 3 + 1], posArr[vi * 3 + 2]];
// Union-Find simples pra agrupar vértices que compartilham alguma face
// (= estão no mesmo pedaço fisicamente conectado da malha).
const parent = new Map();
function find(x) {
let root = x;
while (parent.get(root) !== root) root = parent.get(root);
while (parent.get(x) !== root) {
const next = parent.get(x);
parent.set(x, root);
x = next;
}
return root;
}
function union(a, b) {
const ra = find(a), rb = find(b);
if (ra !== rb) parent.set(ra, rb);
}
const faceCount = Math.floor(indices.length / 3);
for (let f = 0; f < faceCount; f++) {
const a = indices[f * 3], b = indices[f * 3 + 1], c = indices[f * 3 + 2];
if (!parent.has(a)) parent.set(a, a);
if (!parent.has(b)) parent.set(b, b);
if (!parent.has(c)) parent.set(c, c);
union(a, b);
union(b, c);
}
const facesByRoot = new Map();
for (let f = 0; f < faceCount; f++) {
const root = find(indices[f * 3]);
if (!facesByRoot.has(root)) facesByRoot.set(root, []);
facesByRoot.get(root).push(f);
}
// Malha inteira é UM pedaço só conectado — nada pra separar/remover.
if (facesByRoot.size <= 1) continue;
const keptFaces = [];
let removedAny = false;
for (const faceList of facesByRoot.values()) {
const vertSet = new Set();
for (const f of faceList) {
vertSet.add(indices[f * 3]);
vertSet.add(indices[f * 3 + 1]);
vertSet.add(indices[f * 3 + 2]);
}
if (isLeaderLinePointCloud([...vertSet].map(at))) {
removedAny = true;
} else {
keptFaces.push(...faceList);
}
}
if (!removedAny || keptFaces.length === 0) continue;
keptFaces.sort((x, y) => x - y);
const newIndices = new indices.constructor(keptFaces.length * 3);
let w = 0;
for (const f of keptFaces) {
newIndices[w++] = indices[f * 3];
newIndices[w++] = indices[f * 3 + 1];
newIndices[w++] = indices[f * 3 + 2];
}
indicesAccessor.setArray(newIndices);
}
}
function classifySystem(key, rawName) {
const target = SOURCE_TARGETS[key];
if (target.system) return target.system;
@@ -263,6 +362,7 @@ for (const { fbx, key } of SOURCES) {
for (const child of node.listChildren()) visit(child);
return;
} else {
if (LEADER_LINE_SOURCE_KEYS.has(key)) stripLeaderLineComponents(mesh);
systemSlug = classifySystem(key, rawName);
// Nomes de muscular/regiões/referências vêm com sufixo ".l"/".r"/
// ".j" (lateralidade) em vez da palavra "Left"/"Right" — sem tirar