regioes anatomicas

Signed-off-by: Rodrigo Bertoldo de Sousa Martins <rodrigo@martinsevieira.adv.br>
This commit is contained in:
Rodrigo Bertoldo de Sousa Martins committed 2026-09-18 11:26:49 -03:00
1 parent 2dc5a167ed
commit 998b7d8ac3
1 file changed
+28 -11
+28 -11
View File
@@ -1,26 +1,43 @@
import { useMemo } from "react"; import { useMemo } from "react";
import { useGLTF } from "@react-three/drei"; import { useGLTF } from "@react-three/drei";
import * as THREE from "three"; import * as THREE from "three";
import { modelUrl } from "../../lib/api.js";
const MODEL_URL = "/mannequin/body-male-realistic.glb"; // "Regions of human body100.fbx" do próprio Z-Anatomy (já convertido pelo
// pipeline como regioes.glb, o mesmo arquivo usado pelo sistema "Regiões
// Anatômicas" no Atlas) — corpo inteiro, dado REAL, já em posição
// anatômica de verdade (não T-pose/A-pose), montado a partir de ~170
// regiões de superfície nomeadas.
//
// Trocamos por esse depois de repetidas tentativas de reposicionar um
// basemesh CC0 de terceiros (Blender Studio Human Base Meshes) via script
// no Blender — sem rig, cada ajuste (braço, pulso) criava um novo defeito
// de malha em algum lugar (pernas deformadas, dedos rasgados...). Esse
// arquivo já vem correto, sem precisar editar nenhum vértice: zero risco
// de defeito de pose, ao custo de não ter a definição muscular esculpida
// do basemesh (é a malha de superfície do Z-Anatomy, não um sculpt).
const MODEL_FILE = "regioes.glb";
// Altura alvo em metros, decidida pra bater com as âncoras de seta/plano já // Altura alvo em metros, decidida pra bater com as âncoras de seta/plano já
// calibradas em PlanesPage.tsx (ex: ombro em y≈1.4, quadril em y≈0.9). // calibradas em PlanesPage.tsx (ex: ombro em y≈1.4, quadril em y≈0.9).
const TARGET_HEIGHT = 1.78; const TARGET_HEIGHT = 1.78;
const SKIN_MATERIAL = new THREE.MeshStandardMaterial({ color: "#c99a7a", roughness: 0.75, metalness: 0.02 });
useGLTF.preload(MODEL_URL); useGLTF.preload(modelUrl(MODEL_FILE));
// Corpo humano esculpido de verdade (não caixas/cilindros) em posição
// anatômica, usado só pela página de Planos Anatômicos — ver
// data-pipeline/scripts/mannequin-asset/README.md pra origem (Blender
// Studio "Human Base Meshes", CC0), licença e como essa malha foi
// reposicionada da pose original (braços afastados) pra anatômica (braços
// ao lado do corpo). Não tem nenhuma relação com o dataset Z-Anatomy usado
// no Atlas — é só uma silhueta externa, sem estruturas internas.
export function Mannequin() { export function Mannequin() {
const { scene } = useGLTF(MODEL_URL); const { scene } = useGLTF(modelUrl(MODEL_FILE));
const normalized = useMemo(() => { const normalized = useMemo(() => {
const clone = scene.clone(true); const clone = scene.clone(true);
// O arquivo real vem com um material por região (a cor "arco-íris" que
// demos pro sistema de Regiões Anatômicas no Atlas) — aqui queremos só
// uma silhueta neutra, então trocamos TUDO por um material de pele
// único, compartilhado (a mesma instância em todo mesh, sem custo
// extra de draw call por isso).
clone.traverse((obj) => {
if (obj instanceof THREE.Mesh) obj.material = SKIN_MATERIAL;
});
const box = new THREE.Box3().setFromObject(clone); const box = new THREE.Box3().setFromObject(clone);
const size = new THREE.Vector3(); const size = new THREE.Vector3();
box.getSize(size); box.getSize(size);
@@ -32,7 +49,7 @@ export function Mannequin() {
group.add(clone); group.add(clone);
// Centraliza em X/Z e põe o pé no chão (y=0) ANTES de escalar, depois // Centraliza em X/Z e põe o pé no chão (y=0) ANTES de escalar, depois
// aplica a escala no grupo pai — assim o pivô da escala é a origem já // aplica a escala no grupo pai — assim o pivô da escala é a origem já
// corrigida, em vez do pivô torto que a malha trouxe do Blender. // corrigida, em vez de um pivô torto vindo da malha original.
clone.position.set(-center.x, -box.min.y, -center.z); clone.position.set(-center.x, -box.min.y, -center.z);
group.scale.setScalar(scale); group.scale.setScalar(scale);
return group; return group;