mars.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. import {
  2. DebugTilesRenderer as TilesRenderer, InfiniteGridHelper
  3. } from '../src/index.js';
  4. import {
  5. Scene,
  6. DirectionalLight,
  7. AmbientLight,
  8. WebGLRenderer,
  9. PerspectiveCamera,
  10. Group,
  11. sRGBEncoding,
  12. FogExp2,
  13. CameraHelper,
  14. Color
  15. } from 'three';
  16. import { FlyOrbitControls } from './FlyOrbitControls.js';
  17. import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
  18. import { LoadingManager } from 'three';
  19. import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
  20. import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
  21. import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils';
  22. let camera, controls, scene, renderer;
  23. let thirdPersonCamera, thirdPersonRenderer, thirdPersonControls, cameraHelper
  24. let groundTiles, skyTiles;
  25. let tilesRendererArr = [];
  26. let statsContainer
  27. const params = {
  28. errorTarget: 45,
  29. displayBoxBounds: false,
  30. fog: false,
  31. showThirdPerson: false,
  32. };
  33. init();
  34. render();
  35. function init() {
  36. const fog = new FogExp2( 0xd8cec0, .0075, 250 );
  37. scene = new Scene();
  38. // primary camera view
  39. renderer = new WebGLRenderer( { antialias: true } );
  40. renderer.setPixelRatio( window.devicePixelRatio );
  41. renderer.setSize( window.innerWidth, window.innerHeight );
  42. renderer.setClearColor( 0xd8cec0 );
  43. renderer.outputEncoding = sRGBEncoding;
  44. document.body.appendChild( renderer.domElement );
  45. renderer.domElement.tabIndex = 1;
  46. camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
  47. camera.position.set( 20, 10, 20 );
  48. cameraHelper = new CameraHelper( camera );
  49. scene.add( cameraHelper );
  50. // controls
  51. controls = new FlyOrbitControls( camera, renderer.domElement );
  52. controls.screenSpacePanning = false;
  53. controls.minDistance = 1;
  54. controls.maxDistance = 2000;
  55. //controls.maxPolarAngle = Math.PI / 2;
  56. controls.baseSpeed = 0.1;
  57. controls.fastSpeed = 0.2;
  58. //加
  59. // Third person camera view
  60. thirdPersonCamera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
  61. thirdPersonCamera.position.set( 50, 40, 40 );
  62. thirdPersonCamera.lookAt( 0, 0, 0 );
  63. thirdPersonRenderer = new WebGLRenderer( { antialias: true } );
  64. thirdPersonRenderer.setPixelRatio( window.devicePixelRatio );
  65. thirdPersonRenderer.setSize( window.innerWidth, window.innerHeight );
  66. thirdPersonRenderer.setClearColor( 0x0f1416 );
  67. thirdPersonRenderer.outputEncoding = sRGBEncoding;
  68. document.body.appendChild( thirdPersonRenderer.domElement );
  69. thirdPersonRenderer.domElement.style.position = 'fixed';
  70. thirdPersonRenderer.domElement.style.left = '5px';
  71. thirdPersonRenderer.domElement.style.bottom = '5px';
  72. thirdPersonRenderer.domElement.style.width = '30%';
  73. thirdPersonRenderer.domElement.style.height = '50%';
  74. thirdPersonRenderer.domElement.tabIndex = 1;
  75. thirdPersonControls = new FlyOrbitControls( thirdPersonCamera, thirdPersonRenderer.domElement );
  76. thirdPersonControls.screenSpacePanning = false;
  77. thirdPersonControls.minDistance = 1;
  78. thirdPersonControls.maxDistance = 2000;
  79. let ground = new InfiniteGridHelper(1, 10000, new Color('#fff'), 10000, 0.2, 0.3)
  80. scene.add(ground)
  81. ground.lookAt(0,1,0)
  82. // lights
  83. const dirLight = new DirectionalLight( 0xffffff );
  84. dirLight.position.set( 1, 2, 3 );
  85. scene.add( dirLight );
  86. const ambLight = new AmbientLight( 0xffffff, 0.2 );
  87. scene.add( ambLight );
  88. const tilesParent = new Group();
  89. tilesParent.rotation.set( Math.PI / 2, 0, 0 );
  90. scene.add( tilesParent );
  91. /*
  92. //groundTiles = new TilesRenderer( 'https://raw.githubusercontent.com/NASA-AMMOS/3DTilesSampleData/master/msl-dingo-gap/0528_0260184_to_s64o256_colorize/0528_0260184_to_s64o256_colorize/0528_0260184_to_s64o256_colorize_tileset.json' );
  93. groundTiles = new TilesRenderer('https://testgis.4dage.com/LVBADUI_qp/tileset.json');
  94. groundTiles.fetchOptions.mode = 'cors';
  95. groundTiles.lruCache.minSize = 900;
  96. groundTiles.lruCache.maxSize = 1300;
  97. groundTiles.errorTarget = 12;
  98. */
  99. //https://testgis.4dage.com/gaoling0805-qp/
  100. loadTileSet('https://testgis.4dage.com/LVBADUI_qp/',camera,renderer);
  101. //loadTileSet('https://testgis.4dage.com/gaoling0805-qp/',camera,renderer);
  102. // skyTiles = new TilesRenderer( 'https://raw.githubusercontent.com/NASA-AMMOS/3DTilesSampleData/master/msl-dingo-gap/0528_0260184_to_s64o256_colorize/0528_0260184_to_s64o256_sky/0528_0260184_to_s64o256_sky_tileset.json' );
  103. // skyTiles.fetchOptions.mode = 'cors';
  104. // skyTiles.lruCache = groundTiles.lruCache;
  105. // tilesParent.add( groundTiles.group, skyTiles.group );
  106. onWindowResize();
  107. window.addEventListener( 'resize', onWindowResize, false );
  108. const gui = new GUI();
  109. gui.add( params, 'fog' ).onChange( v => {
  110. scene.fog = v ? fog : null;
  111. } );
  112. gui.add( params, 'displayBoxBounds' );
  113. gui.add( params, 'errorTarget', 0, 100 );
  114. gui.add( params, 'showThirdPerson' );
  115. gui.open();
  116. statsContainer = document.createElement( 'div' );
  117. statsContainer.style.position = 'absolute';
  118. statsContainer.style.top = 0;
  119. statsContainer.style.left = 0;
  120. statsContainer.style.color = 'white';
  121. statsContainer.style.width = '100%';
  122. statsContainer.style.textAlign = 'center';
  123. statsContainer.style.padding = '5px';
  124. statsContainer.style.pointerEvents = 'none';
  125. statsContainer.style.lineHeight = '1.5em';
  126. document.body.appendChild( statsContainer );
  127. /* // Stats
  128. stats = new Stats();
  129. stats.showPanel( 0 );
  130. document.body.appendChild( stats.dom ); */
  131. }
  132. function loadTileSet(qzpath,camera,renderer){
  133. // 加载json,解析json 取出children中的路径进行拼装加载
  134. //const qzpath = 'http://192.168.1.136:8077/sqsftilte/'
  135. //get(qzpath + 'tileset.json').then((res)=>{
  136. //debugger;
  137. fetch(qzpath + 'tileset.json').then(response => response.json()).then(data => {
  138. console.log(data)
  139. const tilesetArr = data.root.children
  140. for (const tilese of tilesetArr) {
  141. // console.log(qzpath + tilese.content.uri)
  142. const tilesRenderer = new TilesRenderer( qzpath + tilese.content.uri )
  143. const gltfLoader = new GLTFLoader( tilesRenderer.manager );
  144. const dracoLoader = new DRACOLoader( tilesRenderer.manager );
  145. dracoLoader.setDecoderPath( 'https://unpkg.com/three@0.128.0/examples/js/libs/draco/gltf/' );
  146. gltfLoader.setDRACOLoader( dracoLoader );
  147. tilesRenderer.manager.addHandler( /\.gltf$/, gltfLoader );
  148. tilesRenderer.manager.addHandler( /\.glb$/, gltfLoader );
  149. tilesRenderer.setCamera( camera )
  150. tilesRenderer.setResolutionFromRenderer( camera, renderer )
  151. const tilesObj = tilesRenderer.group
  152. tilesObj.rotation.set(-Math.PI / 2, 0, 0)
  153. scene.add( tilesObj )
  154. tilesRendererArr.push(tilesRenderer)
  155. //xzw: Multiple TilesRenderers with Shared Caches and Queues
  156. if(tilesRendererArr[0]){
  157. // set the second renderer to share the cache and queues from the first, 否则卡顿.
  158. tilesRenderer.lruCache = tilesRendererArr[0].lruCache;
  159. tilesRenderer.downloadQueue = tilesRendererArr[0].downloadQueue;
  160. tilesRenderer.parseQueue = tilesRendererArr[0].parseQueue;
  161. } //但还是比只有一个tileRenderer卡顿
  162. }
  163. });
  164. // fetch(qzpath + 'tileset.json').then((res)=>{
  165. // // console.log(res)
  166. // const tilesetArr = res.root.children
  167. // for (const tilese of tilesetArr) {
  168. // // console.log(qzpath + tilese.content.uri)
  169. // const tilesRenderer = new TilesRenderer( qzpath + tilese.content.uri )
  170. // tilesRenderer.setCamera( camera )
  171. // tilesRenderer.setResolutionFromRenderer( camera, renderer )
  172. // const tilesObj = tilesRenderer.group
  173. // tilesObj.rotation.set(-Math.PI / 2, 0, 0)
  174. // scene.add( tilesObj )
  175. // tilesRendererArr.push(tilesRenderer)
  176. // }
  177. //})
  178. }
  179. function onWindowResize() {
  180. camera.aspect = window.innerWidth / window.innerHeight;
  181. camera.updateProjectionMatrix();
  182. renderer.setSize( window.innerWidth, window.innerHeight );
  183. renderer.setPixelRatio( window.devicePixelRatio );
  184. thirdPersonCamera.aspect = thirdPersonRenderer.domElement.clientWidth / thirdPersonRenderer.domElement.clientHeight;
  185. thirdPersonCamera.updateProjectionMatrix();
  186. thirdPersonRenderer.setSize( thirdPersonRenderer.domElement.clientWidth, thirdPersonRenderer.domElement.clientHeight, false);
  187. thirdPersonRenderer.setPixelRatio( window.devicePixelRatio );
  188. }
  189. function render() {
  190. requestAnimationFrame( render );
  191. camera.updateMatrixWorld();
  192. cameraHelper.visible = false;
  193. let downloading = 0, parsing = 0, visibles = 0, count = 0
  194. for (const tilesRenderer of tilesRendererArr) {
  195. //xzw add ---------
  196. tilesRenderer.errorTarget = params.errorTarget;
  197. tilesRenderer.displayBoxBounds = params.displayBoxBounds;
  198. //-----------------
  199. tilesRenderer.update()
  200. downloading += tilesRenderer.stats.downloading
  201. parsing += tilesRenderer.stats.parsing
  202. visibles += tilesRenderer.group.children.length - 2
  203. const geomSet = new Set();
  204. tilesRenderer.traverse( tile => {
  205. const scene = tile.cached.scene;
  206. if ( scene ) {
  207. scene.traverse( c => {
  208. if ( c.geometry ) {
  209. geomSet.add( c.geometry );
  210. }
  211. } );
  212. }
  213. } );
  214. geomSet.forEach( g => {
  215. let u = BufferGeometryUtils.estimateBytesUsed( g );
  216. count += u
  217. //console.log(g.uuid)
  218. } );
  219. }
  220. let cacheFullness = tilesRendererArr[0] ? tilesRendererArr[0].lruCache.itemList.length / tilesRendererArr[0].lruCache.maxSize : 0;
  221. // render third person view
  222. thirdPersonRenderer.domElement.style.visibility = params.showThirdPerson ? 'visible' : 'hidden';
  223. if ( params.showThirdPerson ) {
  224. if(thirdPersonRenderer.domElement.style != 'block'){
  225. thirdPersonRenderer.domElement.style.display = 'block'
  226. onWindowResize()
  227. }
  228. cameraHelper.update();
  229. cameraHelper.visible = true//! params.orthographic;
  230. /* if ( params.showSecondView ) {
  231. secondCameraHelper.update();
  232. secondCameraHelper.visible = true;
  233. }
  234. */
  235. //const dist = thirdPersonCamera.position.distanceTo( rayIntersect.position );
  236. //rayIntersect.scale.setScalar( dist * thirdPersonCamera.fov / 6000 );
  237. thirdPersonRenderer.render( scene, thirdPersonCamera );
  238. }else{
  239. thirdPersonRenderer.domElement.style.display = 'none'
  240. }
  241. renderer.render( scene, camera );
  242. let str = `Downloading: ${ downloading } Parsing: ${ parsing } Visible: ${visibles}`;
  243. //if ( params.enableCacheDisplay ) {
  244. str += `<br/>Cache: ${ ( 100 * cacheFullness ).toFixed( 2 ) }% ~${ ( count / 1000 / 1000 ).toFixed( 2 ) }mb`;
  245. //}
  246. //if ( params.enableRendererStats ) {
  247. const memory = renderer.info.memory;
  248. const programCount = renderer.info.programs.length;
  249. str += `<br/>Geometries: ${ memory.geometries } Textures: ${ memory.textures } Programs: ${ programCount }`;
  250. //}
  251. //if ( statsContainer.innerHTML !== str ) {
  252. statsContainer.innerHTML = str;
  253. //}
  254. }