| 12345678910111213141516171819202122232425262728293031 |
- // Offline pose sweep using recorded HPR and installed Cesium camera/frustum math.
- import assert from 'node:assert/strict'
- import {readFileSync,writeFileSync} from 'node:fs'
- import {resolve,join} from 'node:path'
- import {Matrix4,Matrix3,Quaternion,Cartesian3,BoundingSphere,Transforms,PerspectiveFrustum,Intersect} from 'cesium'
- import {contentAdmission,selectDetailRegions} from '../../src/modules/cockpit/services/regionLoading.js'
- const root=resolve('tools/city-massing/city/cad-bim'),v6=JSON.parse(readFileSync(join(root,'city-regions-v6/manifest.json'))),v7=JSON.parse(readFileSync(join(root,'city-regions-v7/manifest.json'))),transform=Matrix4.fromArray(v7.transform)
- const pivot={lon:110.39028164000001,lat:28.4436787,height:111.57951503970997},radians=n=>n*Math.PI/180
- function camera(heading,pitch,range){
- const target=Cartesian3.fromDegrees(pivot.lon,pivot.lat,pivot.height),local=Transforms.eastNorthUpToFixedFrame(target)
- const qp=Quaternion.fromAxisAngle(Cartesian3.UNIT_Y,-radians(pitch)),qh=Quaternion.fromAxisAngle(Cartesian3.UNIT_Z,-(radians(heading)-Math.PI/2)),rot=Matrix3.fromQuaternion(Quaternion.multiply(qh,qp,new Quaternion()))
- const offset=Matrix3.multiplyByVector(rot,Cartesian3.UNIT_X,new Cartesian3());Cartesian3.multiplyByScalar(offset,-range,offset)
- const direction=Cartesian3.normalize(Cartesian3.negate(offset,new Cartesian3()),new Cartesian3()),right=Cartesian3.normalize(Cartesian3.cross(direction,Cartesian3.UNIT_Z,new Cartesian3()),new Cartesian3()),up=Cartesian3.normalize(Cartesian3.cross(right,direction,new Cartesian3()),new Cartesian3())
- return {position:Matrix4.multiplyByPoint(local,offset,new Cartesian3()),direction:Matrix4.multiplyByPointAsVector(local,direction,new Cartesian3()),up:Matrix4.multiplyByPointAsVector(local,up,new Cartesian3())}
- }
- function sphere(volume){assert.ok(volume.sphere);const s=volume.sphere;return new BoundingSphere(Matrix4.multiplyByPoint(transform,new Cartesian3(...s.slice(0,3)),new Cartesian3()),s[3])}
- const samples=[]
- for(const range of [12000,1560.344530541111,469.96674118784495,180,120])for(const pitch of [-55,-18])for(const heading of [0,90,180,270]){
- const pose=camera(heading,pitch,range),frustum=new PerspectiveFrustum({fov:Math.PI/3,aspectRatio:1440/810,near:1,far:14000}),volume=frustum.computeCullingVolume(pose.position,pose.direction,pose.up)
- const visible=s=>volume.computeVisibility(s)!==Intersect.OUTSIDE,dist=s=>Cartesian3.distance(pose.position,s.center)
- function candidates(manifest,useContent){return manifest.regions.map(r=>{const actual=(v7.regions[r.id].admissionBounds).map(sphere),bounds=(useContent?r.admissionBounds:[r.bounds]).map(sphere),admission=contentAdmission(bounds,visible,dist);return{...r,...admission,retryAt:0,active:false,actualVisibleContents:actual.filter(visible).length}})}
- const old=candidates(v6,false),next=candidates(v7,true),selected=selectDetailRegions(next),records=selected.map(id=>next.find(r=>r.id===id)),oldSelected=selectDetailRegions(old)
- assert.ok(records.every(r=>r.actualVisibleContents>0));assert.ok(records.length<=2&&records.reduce((s,r)=>s+r.contentCount,0)<=180&&records.reduce((s,r)=>s+r.decodedGeometryBytes,0)<=96*1024*1024)
- assert.deepEqual(selectDetailRegions(next,{pipeline:true}),[])
- samples.push({heading,pitch,range,cameraECEF:{position:[pose.position.x,pose.position.y,pose.position.z],direction:[pose.direction.x,pose.direction.y,pose.direction.z],up:[pose.up.x,pose.up.y,pose.up.z]},oldRegions:oldSelected,oldSelectedWithNoActualVisibleContent:oldSelected.filter(id=>!old.find(r=>r.id===id).actualVisibleContents),newRegions:selected,newVisibleContentBounds:records.map(r=>({id:r.id,visibleBounds:r.actualVisibleContents,distance:r.distance})),contents:records.reduce((s,r)=>s+r.contentCount,0),decodedEstimate:records.reduce((s,r)=>s+r.decodedGeometryBytes,0),pipelineRegions:0})
- }
- const recorded=samples.find(s=>s.heading===0&&s.pitch===-55&&s.range===469.96674118784495)
- assert.deepEqual(recorded.oldSelectedWithNoActualVisibleContent,[64,39],'recorded-pose fixture must reproduce old empty admissions')
- assert.deepEqual(recorded.newRegions,[78,77],'actual-content admission selects the nearby visible bounds')
- const report={passed:true,recordedPivot:pivot,samples,frustumAssumption:'60 degree FOV, 1440x810 canvas; actual browser FOV not captured',activeHistoryApplied:false,renderingValidated:false,gpuMeasured:false,scope:'Cesium HPR/frustum math, selected content-bounds visibility and declared aggregate budgets only'}
- writeFileSync(process.argv[2]||'.scratch/cockpit-shell-panel-layout/verify/artifacts/t35/admission-pose-sweep-v7.json',JSON.stringify(report,null,2));console.log(JSON.stringify({passed:true,poses:samples.length,oldEmptySelections:samples.reduce((s,r)=>s+r.oldSelectedWithNoActualVisibleContent.length,0),newEmptySelections:0,recordedHeading0:samples.filter(s=>s.heading===0&&s.pitch===-55),renderingValidated:false}))
|