mergeStartTest.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. import * as THREE from "../../libs/three.js/build/three.module.js";
  2. import {settings, config} from './settings.js'
  3. import math from './utils/math.js'
  4. import browser from './utils/browser.js'
  5. import {Utils} from "./../utils.js"
  6. import cameraLight from './utils/cameraLight.js'
  7. import './three.shim.js'
  8. import "./potree.shim.js"
  9. //多元融合模块
  10. var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m
  11. //设置:
  12. Potree.settings.editType = 'merge'
  13. Potree.settings.sidebar = 'sidebar2.html'
  14. Potree.settings.intersectOnObjs = true
  15. Potree.settings.boundAddObjs = true
  16. Potree.settings.showCompass = true
  17. Potree.settings.number = number || 't-o5YMR13'// 't-iksBApb'// 写在viewer前
  18. Potree.fileServer = fileServer
  19. webSite && (Potree.settings.webSite = webSite)
  20. let viewer = new Potree.Viewer(dom , mapDom);
  21. let Alignment = viewer.modules.Alignment
  22. viewer.setEDLEnabled(false);
  23. viewer.setFOV(config.view.fov);
  24. viewer.loadSettingsFromURL();
  25. {
  26. viewer.mainViewport.view.position.set(100,100,200)
  27. viewer.mainViewport.view.lookAt(0,0,0)
  28. viewer.updateModelBound()//init
  29. //this.bound = new THREE.Box3(new THREE.Vector3(-1,-1,-1),new THREE.Vector3(1,1,1))
  30. viewer.transformationTool.setModeEnable('scale',false)
  31. viewer.ssaaRenderPass.sampleLevel = 0 //奇怪好像没啥锯齿? sampleLevel为1 的话,ground就不会
  32. }
  33. if(!Potree.settings.isOfficial){
  34. viewer.loadGUI(() => {
  35. viewer.setLanguage('en');
  36. //$("#menu_appearance").next().show();
  37. //$("#menu_tools").next().show();
  38. //$("#menu_scene").next().hide();
  39. $("#mergeModel").show();
  40. viewer.toggleSidebar();
  41. });
  42. Potree.settings.sizeFitToLevel = true//当type为衰减模式时自动根据level调节大小。每长一级,大小就除以2
  43. }
  44. Potree.loadDatasetsCallback = function(data, ifReload){
  45. if(!data || data.length == 0)return console.error('getDataSet加载的数据为空')
  46. Potree.datasetData = data
  47. viewer.transform = null
  48. var datasetLength = data.length
  49. var pointcloudLoaded = 0
  50. var panosLoaded = 0
  51. var pointcloudLoadDone = function(){//点云cloud.js加载完毕后
  52. viewer.updateModelBound()
  53. let {boundSize, center} = viewer.bound
  54. Potree.Log(`中心点: ${math.toPrecision(center.toArray(),2)}, boundSize: ${math.toPrecision(boundSize.toArray(),2)} ` , null, 12)
  55. if(!Potree.settings.isOfficial){
  56. Potree.loadMapEntity('all') //加载floorplan
  57. }
  58. if(!ifReload){
  59. /* viewer.scene.view.setView({
  60. position: center.clone().add(new THREE.Vector3(10,5,10)),
  61. target: center
  62. }) */
  63. viewer.dispatchEvent({type:'loadPointCloudDone'})
  64. if(!Potree.settings.UserPointDensity){
  65. Potree.settings.UserPointDensity = 'high'//'middle'
  66. }
  67. Potree.Log('loadPointCloudDone 点云加载完毕', null, 10)
  68. }
  69. }
  70. var panosLoadDone = function(){
  71. viewer.images360.loadDone()
  72. viewer.scene.add360Images(viewer.images360);
  73. {//初始位置
  74. var urlFirstView = false
  75. var panoId = browser.urlHasValue('pano',true);
  76. if(panoId !== ''){
  77. var pos
  78. var pano = viewer.images360.panos.find(e=>e.id==panoId);
  79. if(pano){
  80. viewer.images360.focusPano({
  81. pano,
  82. duration:0,
  83. callback:()=>{/* Potree.settings.displayMode = 'showPanos' */}
  84. })
  85. }
  86. }else{//考虑到多数据集距离很远,或者像隧道那种场景,要使视野范围内一定能看到点云,最好初始点设置在漫游点上
  87. let {boundSize, center} = viewer.bound
  88. //let pano = viewer.images360.findNearestPano(center)
  89. }
  90. }
  91. console.log('allLoaded')
  92. viewer.dispatchEvent('allLoaded')
  93. }
  94. var transformPointcloud = (pointcloud, dataset)=>{
  95. var locationLonLat = dataset.location.slice(0,2)
  96. //当只有一个dataset时,无论如何transform 点云和漫游点都能对应上。
  97. var location = viewer.transform.lonlatToLocal.forward(locationLonLat) //transform.inverse()
  98. //初始化位置
  99. viewer.sidebar && viewer.sidebar.addAlignmentButton(pointcloud)
  100. Alignment.rotate(pointcloud, null, dataset.orientation)
  101. Alignment.translate(pointcloud, new THREE.Vector3(location[0], location[1], dataset.location[2]))
  102. pointcloud.updateMatrixWorld()
  103. Potree.Log(`点云${pointcloud.dataset_id}旋转值:${pointcloud.orientationUser}, 位置${math.toPrecision(pointcloud.translateUser.toArray(),3)}, 经纬度 ${locationLonLat}, spacing ${pointcloud.material.spacing}`, null, 17 )
  104. }
  105. if(!Potree.settings.originDatasetId)Potree.settings.originDatasetId = data[0].id
  106. var originDataset = data.find(e=>e.id == Potree.settings.originDatasetId)
  107. {//拿初始数据集作为基准。它的位置是000
  108. var locationLonLat = originDataset.location.slice(0,2)
  109. proj4.defs("NAVVIS:TMERC", "+proj=tmerc +ellps=WGS84 +lon_0=" + locationLonLat[0].toPrecision(15) + " +lat_0=" + locationLonLat[1].toPrecision(15));
  110. proj4.defs("WGS84", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
  111. let transform1 = proj4("WGS84", "NAVVIS:TMERC"); //这个ok TMERC是展开的平面投影
  112. let transform2 = proj4("+proj=tmerc +lat_0=0 +lon_0=123 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs;");
  113. viewer.transform = {
  114. lonlatToLocal : transform1,
  115. lonlatTo4550 : transform2 // 转大地坐标EPSG:4550
  116. }
  117. viewer.mapViewer && viewer.mapViewer.mapLayer.maps[0].updateProjection()
  118. }
  119. data.forEach((dataset,index)=>{
  120. if(!ifReload){
  121. var datasetCode = dataset.sceneCode || dataset.name //对应4dkk的场景码
  122. var cloudPath = `${Potree.settings.urls.prefix1}/${Potree.settings.webSite}/${datasetCode}/data/${datasetCode}/webcloud/cloud.js`
  123. var timeStamp = dataset.createTime ? dataset.createTime.replace(/[^0-9]/ig,'') : ''; //每重算一次后缀随createTime更新一次
  124. //console.warn(dataset.name, 'timeStamp', timeStamp)
  125. Potree.loadPointCloud(cloudPath, dataset.name ,datasetCode, timeStamp, e => {
  126. let scene = viewer.scene;
  127. let pointcloud = e.pointcloud;
  128. let config = Potree.config.material
  129. let material = pointcloud.material;
  130. material.minSize = config.minSize
  131. material.maxSize = config.maxSize
  132. material.pointSizeType = config.pointSizeType //Potree.PointSizeType[config.pointSizeType]//Potree.PointSizeType.ADAPTIVE;//FIXED
  133. pointcloud.changePointSize(config.realPointSize) //material.size = config.pointSize;
  134. pointcloud.changePointOpacity(1)
  135. material.shape = Potree.PointShape.SQUARE;
  136. pointcloud.color = pointcloud.material.color = dataset.color
  137. pointcloud.dataset_id = dataset.id;//供漫游点找到属于的dataset点云
  138. pointcloud.timeStamp = timeStamp
  139. transformPointcloud(pointcloud,dataset)
  140. scene.addPointCloud(pointcloud);
  141. pointcloudLoaded ++;
  142. if(pointcloudLoaded == datasetLength)pointcloudLoadDone()
  143. Potree.loadPanos(dataset.id, (data) => {
  144. //console.log('loadPanos',dataset.sceneCode, dataset.id, data)
  145. viewer.images360.addPanoData(data, dataset.id )
  146. panosLoaded ++;
  147. if(panosLoaded == datasetLength){
  148. panosLoadDone()
  149. }
  150. })
  151. })
  152. }else{
  153. let pointcloud = viewer.scene.pointclouds.find(p => p.dataset_id == dataset.id)
  154. if(!pointcloud){
  155. Potree.Log('数据集id变了,自动使用第一个','#500')
  156. pointcloud = viewer.scene.pointclouds[0]
  157. }
  158. //先归零
  159. Alignment.translate(pointcloud, pointcloud.translateUser.clone().negate())
  160. Alignment.rotate(pointcloud, null, - pointcloud.orientationUser)
  161. transformPointcloud(pointcloud, dataset)
  162. }
  163. })
  164. }
  165. let setMatrix = (pointcloud)=>{//为了漫游点变换,要算一下 类似setMatrix
  166. pointcloud.updateMatrixWorld()
  167. /* pointcloud.transformMatrix = new THREE.Matrix4().multiplyMatrices(pointcloud.matrix, pointcloud.pos1MatrixInvert)//还原一点位移
  168. pointcloud.transformInvMatrix.copy(pointcloud.transformMatrix).invert()
  169. pointcloud.rotateMatrix = new THREE.Matrix4().makeRotationFromEuler(pointcloud.rotation);
  170. pointcloud.rotateInvMatrix.copy(pointcloud.rotateMatrix).invert()
  171. pointcloud.panos.forEach(e=>e.transformByPointcloud()) */
  172. pointcloud.updateBound()
  173. pointcloud.getPanosBound()
  174. viewer.updateModelBound()
  175. }
  176. let moveModel = (e)=>{//根据鼠标移动的位置改变位置
  177. let camera = viewer.mainViewport.camera
  178. var origin = new THREE.Vector3(e.pointer.x, e.pointer.y, -1).unproject(camera),
  179. end = new THREE.Vector3(e.pointer.x, e.pointer.y, 1).unproject(camera)
  180. var dir = end.sub(origin)
  181. let planeZ = 0;
  182. let r = (planeZ - origin.z)/dir.z
  183. let x = r * dir.x + origin.x
  184. let y = r * dir.y + origin.y
  185. /* if(modelType == 'laser'){
  186. // modelEditing.translateUser.copy(pos)
  187. //Alignment.setMatrix(modelEditing)
  188. let pos = new THREE.Vector3(x,y, planeZ )
  189. modelEditing.position.copy(modelEditing.initialPosition).add(pos)
  190. }else{
  191. let pos = new THREE.Vector3(x,y, modelEditing.position.z )
  192. modelEditing.position.copy(pos)
  193. } */
  194. MergeEditor.moveBoundCenterTo(modelEditing,new THREE.Vector3(x,y, modelEditing.boundCenter.z)) //使模型中心的xy在鼠标所在位置
  195. modelEditing.dispatchEvent("position_changed")
  196. }
  197. let cancelMove = ()=>{
  198. modelEditing = null
  199. viewer.removeEventListener('global_mousemove', moveModel);
  200. viewer.removeEventListener('global_click', confirmPos);
  201. }
  202. let confirmPos = ()=>{
  203. focusOnSelect(modelEditing)
  204. cancelMove()
  205. return {stopContinue:true}
  206. }
  207. let focusOnSelect = (object, duration = 400)=>{
  208. let boundingBox = object.boundingBox.clone().applyMatrix4(object.matrixWorld)
  209. let center = boundingBox.getCenter(new THREE.Vector3)
  210. let size = boundingBox.getSize(new THREE.Vector3)
  211. let maxSize = size.length() //对角线长度
  212. if(object.isPointcloud){
  213. maxSize /= 2
  214. }
  215. let hfov = cameraLight.getHFOVForCamera(viewer.mainViewport.camera,true)
  216. let minRadius = maxSize / Math.tan(hfov/2)
  217. //viewer.mainViewport.view.lookAt(center)
  218. viewer.mainViewport.view.setView({
  219. position: center.clone().sub(viewer.mainViewport.view.direction.clone().multiplyScalar(minRadius)),
  220. target: center,
  221. duration
  222. }) //setView can cancel bump
  223. }
  224. viewer.setControls(viewer.orbitControls)
  225. let tilesetUrls = [
  226. 'https://4dkk.4dage.com/fusion/test/b3dm/tileset.json', //高层小区
  227. 'https://testgis.4dage.com/LVBADUI_qp/tileset.json', //村庄
  228. 'https://4dkk.4dage.com/fusion/testb3dm/modelId_613/tileset.json',//"952.16MB" 港一
  229. 'https://4dkk.4dage.com/fusion/testb3dm/modelId_609/tileset.json',//618.37MB 田野 'https://4dkk.4dage.com/fusion/test/b3dmtest001/tileset.json',
  230. 'https://4dkk.4dage.com/fusion/test/model/modelId_614/tileset.json',//172.97MB 国家电网 //'https://4dkk.4dage.com/fusion/test/model/modelId_602/tileset.json',
  231. 'https://4dkk.4dage.com/fusion/test/model/modelId_602/Tile_016_011/tileset.json', //modelId_614的一部分
  232. //'https://4dkk.4dage.com/fusion/test/model/modelId_570/3dt/3dtiles.json', //only has boundingVolume.sphere 拉远了特别模糊,凑近了模型不太对
  233. ], tileIndex = 0
  234. let modelType, modelEditing, MergeEditor = viewer.modules.MergeEditor
  235. Potree.addModel = function(name, done){
  236. let isFirstLoad = true
  237. cancelMove()
  238. modelType = name
  239. let loadDone = (model)=>{
  240. if(isFirstLoad){
  241. modelEditing = model;
  242. MergeEditor.setModelBtmHeight(model, 0) //默认离地高度为0
  243. /* if(name == '3dTiles'){
  244. setTimeout(()=>{
  245. moveModel({pointer:{x:0,y:0}}) //3dTiles的移动会错乱,先默认放在当前视图中间吧
  246. confirmPos()
  247. },1)
  248. }else{ */
  249. viewer.addEventListener('global_mousemove', moveModel);
  250. viewer.addEventListener('global_click', confirmPos, 3);
  251. //}
  252. }else{
  253. modelEditing = null
  254. }
  255. {//transform
  256. let updateBound = ()=>{
  257. model.updateMatrixWorld()
  258. viewer.updateModelBound()
  259. }
  260. let maintainBtmZAndCenter = ()=>{
  261. MergeEditor.maintainBoundXY(model)
  262. MergeEditor.setModelBtmHeight(model)
  263. updateBound()
  264. model.dispatchEvent('transformChanged')
  265. }
  266. model.addEventListener('position_changed', ()=>{
  267. updateBound()
  268. MergeEditor.getBoundCenter(model);//更新boundcenter
  269. MergeEditor.computeBtmHeight(model)
  270. model.dispatchEvent('transformChanged')
  271. })
  272. model.addEventListener("rotation_changed", maintainBtmZAndCenter )
  273. model.addEventListener("scale_changed", maintainBtmZAndCenter )
  274. model.addEventListener('transformChanged', ()=>{
  275. MergeEditor.modelTransformCallback(model)
  276. })
  277. }
  278. model.updateMatrixWorld()
  279. viewer.updateModelBound()
  280. model.lastMatrixWorld = model.matrixWorld.clone();
  281. MergeEditor.getBoundCenter(model) //初始化
  282. model.addEventListener('changeSelect',(e)=>{
  283. e.selected ? MergeEditor.transformControls.attach(model) : MergeEditor.transformControls.detach()
  284. //viewer.transformObject(e.selected ? model : null);
  285. })
  286. done(model)
  287. }
  288. if(name == 'laser'){
  289. Potree.loadDatasets(Potree.loadDatasetsCallback)
  290. viewer.addEventListener('allLoaded',()=>{
  291. let pointcloud = modelEditing = viewer.scene.pointclouds[0];
  292. pointcloud.matrixAutoUpdate = true
  293. pointcloud.initialPosition = pointcloud.position.clone()
  294. /* pointcloud.addEventListener('select',(e)=>{
  295. if(Potree.settings.displayMode == 'showPanos')return
  296. console.log('select',e)
  297. //viewer.setControls(viewer.orbitControls)
  298. focusOnSelect(pointcloud)
  299. viewer.outlinePass.selectedObjects = [pointcloud]
  300. return {stopContinue:true}
  301. },1)
  302. pointcloud.addEventListener('deselect',(e)=>{
  303. console.log('deselect',e)
  304. //viewer.setControls(viewer.fpControls)
  305. viewer.outlinePass.selectedObjects = []
  306. }) */
  307. loadDone(pointcloud)
  308. })
  309. }else{
  310. let callback = (object)=>{
  311. //focusOnSelect(object, 1000)
  312. object.traverse(e=>e.material && (e.material.transparent = true))
  313. object.isModel = true
  314. object.dataset_id = Date.now() //暂时
  315. /* object.addEventListener('select',(e)=>{
  316. if(Potree.settings.displayMode == 'showPanos')return
  317. console.log('select',e)
  318. viewer.setControls(viewer.orbitControls)
  319. focusOnSelect(object)
  320. viewer.outlinePass.selectedObjects = [object]
  321. return {stopContinue:true}
  322. },1)
  323. object.addEventListener('deselect',(e)=>{
  324. console.log('deselect',e)
  325. viewer.setControls(viewer.fpControls)
  326. viewer.outlinePass.selectedObjects = []
  327. }) */
  328. /* object.addEventListener('click',(e)=>{
  329. //只是为了能得到hoverElement识别才加这个侦听
  330. }) */
  331. $('#log').text('')
  332. loadDone(object)
  333. }
  334. let onprogress = (num)=>{
  335. $('#log').text("已加载 " + Math.round(num) +" %")
  336. }
  337. if(name == '4dkk'){
  338. let num = 't-yAWONOn'
  339. var path = `${Potree.scriptPath}/data/4dkk/${num}/`
  340. viewer.loadModel({
  341. name,
  342. objurl: path+'mesh.obj', //0.6s
  343. mtlurl: path+'mesh.mtl',
  344. unlit:true,
  345. transform :{
  346. rotation : [0, 0, 0],
  347. position : [0,0,0]
  348. }
  349. },callback,onprogress)
  350. }else if(name == 'obj'){
  351. /* var path = `${Potree.resourcePath}/models/13/`
  352. viewer.loadModel({
  353. name,
  354. objurl: path+'w13.OBJ',
  355. mtlurl: path+'w13.mtl',
  356. transform : {
  357. rotation : [Math.PI/2, 0, 0],
  358. position : [0,0,0]
  359. }
  360. },callback,onprogress) */
  361. var path = `${Potree.resourcePath}/models/obj/28M/`
  362. viewer.loadModel({
  363. name,
  364. objurl: path+'GW1H.obj', //解析时间4.392s
  365. mtlurl: path+'GW1H.mtl',
  366. transform : {
  367. rotation : [0, 0, 0],
  368. position : [0,0,0]
  369. }
  370. },callback,onprogress)
  371. /* var path = `${Potree.resourcePath}/models/obj/75M/`
  372. viewer.loadModel({
  373. name,
  374. objurl: path+'Tile_+070_+051.obj', //解析时间4.945s
  375. mtlurl: path+'Tile_+070_+051.mtl',
  376. transform : {
  377. rotation : [0, 0, 0],
  378. position : [0,0,0]
  379. }
  380. },callback,onprogress) */
  381. /* var path = `${Potree.resourcePath}/models/obj/496M/`
  382. viewer.loadModel({
  383. name,
  384. objurl: path+'Model.obj', //解析时间25.629 s 期间弹出崩溃提示。很卡
  385. mtlurl: path+'Model.mtl',
  386. transform : {
  387. rotation : [0, 0, 0],
  388. position : [0,0,0]
  389. }
  390. },callback,onprogress) */
  391. }else if(name == 'glb'){
  392. let angle = 0
  393. let fileName = '87b3a367bc3e4273832cb4fa398782e5.glb'
  394. /* let angle = Math.PI/2
  395. let fileName = 'coffeemat.glb', //0.3s */
  396. /* let angle = Math.PI/2
  397. let fileName = 'ModernJPHouseSofa44216499.glb' // 21M
  398. */
  399. /* let angle = 0
  400. let fileName = 'cloud_glb_47_loadErrored.glb' //176M */
  401. var path = `${Potree.resourcePath}/models/glb/`
  402. viewer.loadModel({
  403. fileType:'glb',
  404. name,
  405. url: path+fileName,
  406. transform : {
  407. rotation : [angle, 0, 0],
  408. position : [0,0,0]
  409. }
  410. },callback,onprogress)
  411. }else if(name == '3dTiles'){
  412. viewer.loadModel({
  413. fileType:'3dTiles',
  414. url: tilesetUrls[tileIndex++],
  415. transform : {
  416. rotation : [Math.PI/2, 0, 0],
  417. position : [0,0,0]
  418. }
  419. },callback,onprogress)
  420. }
  421. }
  422. }
  423. let getModelByName = (name)=>{
  424. if(name == 'laser'){
  425. return viewer.scene.pointclouds[0]
  426. }else{
  427. return viewer.objs.children.find(e=>e.name == name)
  428. }
  429. }
  430. Potree.removeModel = function(name){
  431. let model = getModelByName(name)
  432. if(name == 'laser'){
  433. viewer.scene.removePointCloud(model);
  434. viewer.updateModelBound()
  435. }else{
  436. viewer.removeObj(model)
  437. }
  438. cancelMove()
  439. }
  440. /* Potree.selectModel = function(name){
  441. let model = getModelByName(name)
  442. model && viewer.transformObject(model)
  443. } */
  444. //Potree.loadDatasets(Potree.loadDatasetsCallback)
  445. viewer.inputHandler.addEventListener('keydown', (e)=>{
  446. if(e.event.key == "e" ){
  447. MergeEditor.transformControls.mode = 'rotate'
  448. }else if(e.event.key == "w"){
  449. MergeEditor.transformControls.mode = 'translate'
  450. }
  451. })
  452. window.THREE = THREE
  453. window.buttonFunction = function(){
  454. viewer.scene.pointclouds.forEach(e=>e.predictNodeMaxLevel())
  455. }
  456. }
  457. /* var changeLog = ()=>{ //如果移动端加了test反而出不来bug的话,用这个
  458. var textarea = document.createElement('textarea');
  459. textarea.id = "consoleLog";
  460. textarea.style.width = '160px';
  461. textarea.style.height = '200px'
  462. textarea.style.position = 'fixed'
  463. textarea.style.right = 0
  464. textarea.style.bottom = '0'
  465. textarea.style['z-index'] = 9999;
  466. textarea.style.color = 'black';
  467. textarea.style.opacity = 0.9;
  468. textarea.style['font-size'] = '12px';
  469. textarea.style['backgroundColor'] = '#ffffff'
  470. document.getElementsByTagName("body")[0].appendChild(textarea);
  471. var list = ["log", "error", "warn", "debug", "info", "time", "timeEnd"]
  472. var exchange = function (o) {
  473. console["old" + o] = console[o];
  474. console[o] = function () {
  475. var args = Array.from(arguments)
  476. console["old" + o].apply(this, arguments)
  477. var t = document.getElementById("consoleLog").innerHTML;
  478. var str = ''
  479. args.forEach(a=>{
  480. str += a + ' '
  481. })
  482. document.getElementById("consoleLog").innerHTML = str + "\n\n" + t;
  483. }
  484. }
  485. for (var i = 0; i < list.length; i++) {
  486. exchange(list[i])
  487. }
  488. }
  489. changeLog() */
  490. //可以直接用edlShader来渲染obj的outline,但不能渲染被遮挡的部分
  491. export {start}