fix exame fisico
This commit is contained in:
1 parent
43df670a55
commit
7e8834fbfd
1 file changed
+38
-7
@@ -119,30 +119,61 @@ function CameraController({ modelFiles }: { modelFiles: string[] }) {
|
||||
// outro ponto) — em vez de assumir uma posição de câmera fixa, sempre
|
||||
// que o conjunto de arquivos carregados muda, enquadra a câmera no
|
||||
// bounding box real de tudo que está na cena.
|
||||
//
|
||||
// O carregamento do .glb é assíncrono (Suspense) e pode levar bem mais
|
||||
// que 1 frame — um único requestAnimationFrame às vezes media a cena
|
||||
// ainda vazia/parcial (só 1-2 ossos montados) e nunca corrige depois,
|
||||
// porque "modelFiles" não muda de novo uma vez carregado. Por isso agora
|
||||
// fica tentando de novo a cada 200ms até o tamanho do conteúdo ficar
|
||||
// ESTÁVEL (duas leituras seguidas iguais = terminou de montar), só então
|
||||
// enquadra a câmera.
|
||||
useEffect(() => {
|
||||
if (!controlsRef.current || modelFiles.length === 0) return;
|
||||
const id = requestAnimationFrame(() => {
|
||||
if (modelFiles.length === 0) return;
|
||||
let cancelled = false;
|
||||
let attempts = 0;
|
||||
let lastSize = -1;
|
||||
let timer: ReturnType<typeof setTimeout>;
|
||||
|
||||
function tryFit() {
|
||||
if (cancelled || !controlsRef.current) return;
|
||||
const box = computeVisibleBoundingBox(scene);
|
||||
if (box.isEmpty()) return;
|
||||
attempts += 1;
|
||||
if (box.isEmpty()) {
|
||||
if (attempts < 50) timer = setTimeout(tryFit, 200);
|
||||
return;
|
||||
}
|
||||
const size = box.getSize(new THREE.Vector3()).length();
|
||||
const stable = Math.abs(size - lastSize) < lastSize * 0.01;
|
||||
lastSize = size;
|
||||
if (!stable && attempts < 50) {
|
||||
timer = setTimeout(tryFit, 200);
|
||||
return;
|
||||
}
|
||||
|
||||
setContentBox({
|
||||
min: [box.min.x, box.min.y, box.min.z],
|
||||
max: [box.max.x, box.max.y, box.max.z],
|
||||
});
|
||||
const size = box.getSize(new THREE.Vector3()).length();
|
||||
// Ajusta os planos de corte da câmera ao tamanho real do conteúdo —
|
||||
// um "far" fixo pequeno cortaria (tornaria invisível) um modelo bem
|
||||
// maior do que o esperado.
|
||||
camera.near = Math.max(size / 1000, 0.001);
|
||||
camera.far = size * 100;
|
||||
if (camera instanceof THREE.PerspectiveCamera) camera.updateProjectionMatrix();
|
||||
controlsRef.current?.fitToBox(box, true, {
|
||||
controlsRef.current.fitToBox(box, true, {
|
||||
paddingLeft: 0.2,
|
||||
paddingRight: 0.2,
|
||||
paddingTop: 0.2,
|
||||
paddingBottom: 0.2,
|
||||
});
|
||||
});
|
||||
return () => cancelAnimationFrame(id);
|
||||
}
|
||||
|
||||
const id = requestAnimationFrame(tryFit);
|
||||
return () => {
|
||||
cancelled = true;
|
||||
cancelAnimationFrame(id);
|
||||
clearTimeout(timer);
|
||||
};
|
||||
}, [modelFiles, scene, camera, setContentBox]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
Reference in new issue
Block a user