diff options
Diffstat (limited to 'public/App.js')
| -rw-r--r-- | public/App.js | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/public/App.js b/public/App.js index c5a5418..f953832 100644 --- a/public/App.js +++ b/public/App.js @@ -58,6 +58,8 @@ export let currentRunId = createAtom(""); export let loadedStepPath = createAtom(undefined); +export let displayedNode = createAtom(undefined); + export let freezeRotation = createAtom(false); export function element(id) { @@ -173,6 +175,7 @@ export function addMesh(view, frame) { export function renderFrame(frame) { selectedFrame(frame); + displayedNode(undefined); if (viewState() != null) { const view = viewState(); view.Group.clear(); @@ -181,11 +184,46 @@ export function renderFrame(frame) { } } +export function frameObject(view, node) { + const box = new THREE.Box3(); + box.setFromObject(node); + if (!box.isEmpty()) { + const center = new THREE.Vector3(); + const size = new THREE.Vector3(); + box.getCenter(center); + box.getSize(size); + const radius = 0.5 * size.length(); + if (radius > 1E-06) { + node.position.set(-center.x, -center.y, -center.z); + const camera = view.Camera; + const aspect = max(1, view.Canvas.clientWidth) / max(1, view.Canvas.clientHeight); + camera.aspect = aspect; + const fovY = (camera.fov * 3.141592653589793) / 180; + const limitingFov = min(fovY, 2 * Math.atan(Math.tan(fovY / 2) * aspect)); + const distance = (1.28 * radius) / Math.sin(limitingFov / 2); + const norm = Math.sqrt(((0.62 * 0.62) + (0.45 * 0.45)) + (0.7 * 0.7)); + camera.position.set((0.62 / norm) * distance, (0.45 / norm) * distance, (0.7 / norm) * distance); + camera.near = max(distance * 0.01, distance - (radius * 2.5)); + camera.far = (distance + (radius * 4)); + camera.lookAt(0, 0, 0); + camera.updateProjectionMatrix(); + } + } +} + export function resizeView(view) { const width = max(1, view.Canvas.clientWidth); const height = max(1, view.Canvas.clientHeight); view.Renderer.setSize(width, height, false); - renderFrame(selectedFrame()); + view.Camera.aspect = (width / height); + view.Camera.updateProjectionMatrix(); + if (displayedNode() == null) { + renderFrame(selectedFrame()); + } + else { + frameObject(view, displayedNode()); + view.Renderer.render(view.Scene, view.Camera); + } } export function initializeView() { @@ -213,6 +251,7 @@ export function initializeView() { const view = new ViewState(renderer, scene, camera, group, canvas); viewState(view); freezeRotation((new URLSearchParams(window.location.search).get("freeze")) === "1"); + window.SOMHAIRLES_VIEWER = { camera: camera, scene: scene, group: group, canvas: canvas }; renderFrame(selectedFrame()); window.addEventListener("resize", (_arg) => { resizeView(view); @@ -262,6 +301,9 @@ export function loadStepArtifact(view, stepPath) { loader.load(url, ((gltf) => { view.Group.clear(); view.Group.add(gltf.scene); + displayedNode(gltf.scene); + frameObject(view, gltf.scene); + view.Renderer.render(view.Scene, view.Camera); setText("viewport-note", toText(printf("管线几何 · %s"))(stepPath)); }), null, ((_arg) => { setText("viewport-note", toText(printf("管线几何加载失败 · %s"))(stepPath)); |
