Files
rhinelab-ui/reference/depth-check.html
T

36 lines
2.4 KiB
HTML

<!doctype html><html lang="zh-CN"><meta charset="utf-8"><title>相机深度范围检查</title>
<style>body{font:14px system-ui;background:#e8e5e1;padding:20px}#scene{width:960px;height:540px}pre{white-space:pre-wrap}</style>
<h1>相机深度范围检查</h1><pre id="result">正在检查…</pre><div id="scene"></div>
<script type="module">
import * as THREE from '/node_modules/three/build/three.module.js';
import {ArchiveScene} from '/src/scene.ts';
const s=new ArchiveScene(document.querySelector('#scene'));
const draw=s.composer.render.bind(s.composer);s.composer.render=()=>{};
const result=document.querySelector('#result'),samples=[];
const ease=t=>{t=Math.max(0,Math.min(1,t));return t*t*t*(t*(6*t-15)+10)};
try{
await s.load();s.setMode('hidden');s.select(0);
for(const time of [27,27.2,27.6,28,29,30,31,32,34,36,39.6]){
const shot=time-5,zoom=.55*ease((shot-27.3)/1.65)+.45*ease((shot-29)/5);
s.update(time,{reveal:1,lift:0,zoom,time:shot});s.scene.updateMatrixWorld(true);
const camera=new THREE.PerspectiveCamera().copy(s.camera);camera.near=.1;camera.updateProjectionMatrix();camera.updateMatrixWorld(true);
const frustum=new THREE.Frustum().setFromProjectionMatrix(new THREE.Matrix4().multiplyMatrices(camera.projectionMatrix,camera.matrixWorldInverse));
let nearest=Infinity,visible=0;const matrix=new THREE.Matrix4(),world=new THREE.Matrix4(),box=new THREE.Box3();
s.scene.traverse(mesh=>{
if(!mesh.isMesh||!mesh.visible||mesh.geometry.type==='PlaneGeometry')return;
mesh.geometry.computeBoundingBox();
for(let i=0;i<(mesh.isInstancedMesh?mesh.count:1);i++){
if(mesh.isInstancedMesh){mesh.getMatrixAt(i,matrix);world.multiplyMatrices(mesh.matrixWorld,matrix)}else world.copy(mesh.matrixWorld);
box.copy(mesh.geometry.boundingBox).applyMatrix4(world);if(!frustum.intersectsBox(box))continue;
visible++;
for(const x of [box.min.x,box.max.x])for(const y of [box.min.y,box.max.y])for(const z of [box.min.z,box.max.z]){
const p=new THREE.Vector3(x,y,z).applyMatrix4(camera.matrixWorldInverse);nearest=Math.min(nearest,-p.z);
}
}
});
samples.push({time,visible,nearest,near:s.camera.near});if(nearest<=s.camera.near)throw Error('可见模型接近裁剪面');
}
draw();result.textContent=JSON.stringify({passed:true,samples},null,2);
}catch(e){result.textContent=JSON.stringify({passed:false,error:String(e),samples},null,2)}
</script></html>