preview.html 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <meta charset="UTF-8" /><title>沅陵建模审查样片</title
  4. ><style>
  5. html,
  6. body,
  7. #map {
  8. margin: 0;
  9. width: 100%;
  10. height: 100%;
  11. overflow: hidden;
  12. background: #071019;
  13. }
  14. #caption {
  15. position: absolute;
  16. left: 18px;
  17. bottom: 28px;
  18. max-width: calc(100% - 48px);
  19. color: #eee;
  20. background: #102131d9;
  21. padding: 10px;
  22. font: 14px sans-serif;
  23. pointer-events: none;
  24. }
  25. </style>
  26. <body>
  27. <div id="map"></div>
  28. <div id="caption">建模审查样片,非测绘数据</div>
  29. <script type="module">
  30. window.CESIUM_BASE_URL = '/cesium/'
  31. const raw = await (await fetch('/src/modules/cockpit/services/cesiumEngine.js')).text()
  32. const url = raw.match(/from\s*["']([^"']*\/cesium\.js[^"']*)["']/)?.[1]
  33. const C = await import(url),
  34. E = await import('/src/modules/cockpit/services/cesiumEngine.js')
  35. window.startPreview = async ({ model, models, terrain = true, imagery = true }) => {
  36. const v = E.createViewer(document.querySelector('#map'), {
  37. ready: true,
  38. kind: 'tms',
  39. url: 'Assets/Textures/NaturalEarthII',
  40. })
  41. if (terrain) await E.applyTerrain(v, { url: '/gis/dem', requestVertexNormals: true })
  42. else v.terrainProvider = new C.EllipsoidTerrainProvider()
  43. if (imagery)
  44. E.applyOverlays(v, [
  45. {
  46. url: '/gis/pic3/{z}/{x}/{reverseY}.png',
  47. minimumLevel: 0,
  48. maximumLevel: 19,
  49. bounds: [109.962, 27.962, 111.046, 29.061],
  50. },
  51. ])
  52. const tileUrls = models || (model ? [model] : [])
  53. const t = await E.applyTilesets(v.scene, tileUrls.map(url => ({ url, lighting: true })))
  54. if (t.failed.length) throw Error(JSON.stringify(t.failed))
  55. v.scene.globe.maximumScreenSpaceError = 1
  56. v.scene.globe.enableLighting = false
  57. // A fixed local daylight is used for asset inspection; terrain imagery stays unlit.
  58. const frame = C.Transforms.eastNorthUpToFixedFrame(C.Cartesian3.fromDegrees(110.395, 28.454))
  59. const sunDir = C.Matrix4.multiplyByPointAsVector(
  60. frame,
  61. new C.Cartesian3(-0.4, -0.6, -1),
  62. new C.Cartesian3()
  63. )
  64. C.Cartesian3.normalize(sunDir, sunDir)
  65. v.scene.light = new C.DirectionalLight({ direction: sunDir, intensity: 3.0 })
  66. v.shadowMap.enabled = false // 避免当前审查场景阴影精度导致立面噪点;不影响地形深度遮挡。
  67. v.shadowMap.softShadows = true
  68. for (const tile of t.instances) {
  69. tile.imageBasedLighting = new C.ImageBasedLighting({
  70. imageBasedLightingFactor: new C.Cartesian2(1, 1),
  71. sphericalHarmonicCoefficients: [
  72. new C.Cartesian3(0.75, 0.75, 0.75),
  73. ...Array.from({ length: 8 }, () => new C.Cartesian3(0, 0, 0)),
  74. ],
  75. })
  76. }
  77. window.scene35 = { C, E, v, tiles: t.instances }
  78. window.frameCount = 0
  79. v.scene.postRender.addEventListener(() => window.frameCount++)
  80. return true
  81. }
  82. if (location.hash !== '#automation') {
  83. await startPreview({
  84. models: [
  85. '/review-assets/district/lod-preview/tileset.json',
  86. '/review-assets/city/regular-estate/lod-preview/tileset.json',
  87. '/review-assets/city/oldtown/lod-preview/tileset.json',
  88. ],
  89. })
  90. const { v, C } = window.scene35
  91. v.scene.screenSpaceCameraController.enableRotate = true
  92. v.scene.screenSpaceCameraController.enableZoom = true
  93. v.scene.screenSpaceCameraController.enableTilt = true
  94. v.scene.screenSpaceCameraController.enableTranslate = true
  95. v.camera.lookAtTransform(
  96. C.Transforms.eastNorthUpToFixedFrame(C.Cartesian3.fromDegrees(110.395, 28.454, 135)),
  97. new C.HeadingPitchRange(0, -0.85, 1250)
  98. )
  99. document.querySelector('#caption').textContent =
  100. '沅陵体育场附近示范街区 · 屋顶/立面样片 · 非全城覆盖,楼层与立面非测绘数据'
  101. }
  102. </script>
  103. </body>
  104. </html>