import assert from 'node:assert/strict'; import {test} from 'node:test'; import * as THREE from 'three'; import {loadTypescript} from './support/load-typescript.mjs'; import {loadFrameGeometry} from './support/load-frame-geometry.mjs'; const {CameraController}=await loadTypescript(new URL('../src/input/CameraController.ts',import.meta.url)); const {prepareHouseAsset,houseRoomBounds}=await loadTypescript(new URL('../src/objects/BlenderHouseSurround.ts',import.meta.url)); const {fitWindowScale}=await loadTypescript(new URL('../src/objects/BlenderWindowFrame.ts',import.meta.url)); test('experimental wall-hug original and courtyard rooms contain zoomed anchored near frusta through open/partial/closed doors',async()=>{ const {SceneZoomController}=await loadTypescript(new URL('../src/input/SceneZoomController.ts',import.meta.url)); const {prepareFrameAsset}=await loadTypescript(new URL('../src/objects/BlenderWindowFrame.ts',import.meta.url)); const {peekingLayout}=await loadTypescript(new URL('../src/objects/PeekingComposition.ts',import.meta.url)); let rays=0; for(const aspect of[375/812,844/390])for(const mode of['original','courtyard'])for(const photoAspect of[.2,.8,5]){ const fit=fitWindowScale(aspect,photoAspect)*.82,layout=mode==='courtyard'?peekingLayout(aspect,photoAspect):{width:fit*photoAspect*.8,height:fit*.8},w=layout.width,h=layout.height,bounds=houseRoomBounds(w,h,.6); const root=loadFrameGeometry(new URL('../public/assets/window/grandma-house-surround.glb',import.meta.url)),room=prepareHouseAsset(root),frame=loadFrameGeometry(),sash=prepareFrameAsset(frame),group=new THREE.Group();group.add(root,frame);room.resize(w,h,.6,layout.clearanceScale,true);sash.resize(w,h,.6); const camera=new THREE.PerspectiveCamera(40,aspect,.1,100),control=new CameraController(camera),zoom=new SceneZoomController(camera);control.setRoomBounds(w,h,.6);control.setCompositionMode('wall'); for(const range of[.75,.9])for(const open of[0,.5,1])for(const [x,y]of[[-1,0],[1,0],[-.5,0],[.5,0],[-1,-1],[1,1],[0,-1]])for(const z of[1,2,3]){ control.setMaxOffset(range);control.setView(x,y);control.update(10,1);sash.setOpen(open);zoom.setZoom(1);zoom.setZoom(z,{x:x,y:y||1});camera.updateMatrixWorld(true);group.updateMatrixWorld(true); for(const px of[-1,0,1])for(const py of[-1,0,1]){const near=new THREE.Vector3(px,py,-1).unproject(camera);assert.ok(near.y>bounds.floor-1e-8&&Math.abs(near.x)!(h.object.material.clippingPlanes??[]).some(p=>p.distanceToPoint(h.point)<0));if(hit)assert.ok(-hit.point.clone().applyMatrix4(camera.matrixWorldInverse).z>=camera.near-1e-7,'nearest room/frame surface stays beyond near plane');rays++;} } room.dispose();sash.dispose(); } console.log('Anchored original/courtyard near-frustum rays:',rays); });