MergeEditor.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. import * as THREE from "../../../../libs/three.js/build/three.module.js";
  2. import cameraLight from '../../utils/cameraLight.js'
  3. import math from "../../utils/math.js"
  4. import Common from '../../utils/Common.js'
  5. import {LineDraw, MeshDraw} from "../../utils/DrawUtil.js";
  6. import {transitions, easing, lerp} from '../../utils/transitions.js'
  7. import SplitScreen from "../../utils/SplitScreen.js";
  8. import InfiniteGridHelper from '../../objects/InfiniteGridHelper.js'
  9. import Compass from "../../objects/tool/Compass.js";
  10. import {TransformControls} from "../../objects/tool/TransformControls.js";
  11. import History from "../../utils/History.js"
  12. const texLoader = new THREE.TextureLoader()
  13. texLoader.crossOrigin = "anonymous"
  14. const edgeStrengths = {
  15. pointcloud: 4,
  16. glb: 100
  17. }
  18. const viewportProps = [{
  19. left:0,
  20. bottom:0,
  21. width: 0.5,height:1,
  22. name : 'top',
  23. axis:["x","y"],
  24. direction : new THREE.Vector3(0,0,-1), //镜头朝向
  25. active: true,
  26. //相机位置在z轴正向
  27. limitBound: new THREE.Box3(new THREE.Vector3(-Infinity,-Infinity, 1),new THREE.Vector3(Infinity,Infinity,5000)), //在地面以上
  28. margin:{x:50, y:150} ,
  29. },
  30. {
  31. left:0.5,
  32. bottom:0,
  33. width: 0.5,height:1,
  34. name : 'right',
  35. axis:["y","z"],
  36. direction : new THREE.Vector3(1,0,0),
  37. active: true,
  38. //相机位置在x轴负向 右下角屏
  39. viewContainsPoints:[new THREE.Vector3(0,0,0)],
  40. margin:{x:300, y:250} ,
  41. } ]
  42. let cylinderSkyGeo, oldSkyGeo
  43. let MergeEditor = {
  44. bus:new THREE.EventDispatcher(),
  45. SplitScreen : new SplitScreen(),
  46. init(){
  47. {
  48. let ground = this.ground = new InfiniteGridHelper(1, 10000, new THREE.Color('#fff'), 10000, 0.2, 0.3)
  49. viewer.scene.scene.add(ground)
  50. //再加两条线否则在正侧边看不到
  51. let line1 = LineDraw.createLine([new THREE.Vector3(-10000, 0, 0),new THREE.Vector3(10000, 0, 0) ], {color:'#666', })
  52. let line2 = LineDraw.createLine([new THREE.Vector3(0, -10000, 0),new THREE.Vector3(0, 10000, 0) ], {mat:line1.material})
  53. ground.renderOrder = Potree.config.renderOrders.model + 1//line1.renderOrder + 1 //要比模型低,否则模型透明时效果不对
  54. ground.add(line1)
  55. ground.add(line2)
  56. ground.material.polygonOffset = true //多边形偏移(视觉上没有移动模型位置),防止闪烁
  57. ground.material.polygonOffsetFactor = 100 //多边形偏移因子
  58. ground.material.polygonOffsetUnits = 10 //多边形偏移单位
  59. ground.material.depthWrite = false
  60. //ground.material.depthTest = false
  61. line1.material.polygonOffset = true
  62. line1.material.polygonOffsetFactor = 130
  63. line1.material.polygonOffsetUnits = 10
  64. line1.material.depthWrite = false
  65. //见笔记:透明物体的材质设置
  66. }
  67. let oriEdgeStrength = viewer.outlinePass.edgeStrength
  68. {
  69. this.transformControls = new TransformControls(viewer.mainViewport.camera, viewer.renderArea,{
  70. dontHideWhenFaceCamera: true,
  71. });
  72. //this.transformControls.space = 'local'//为了在当前方向上平移
  73. this.transformControls.setSize(1.5)
  74. viewer.scene.scene.add(this.transformControls)
  75. this.transformControls._gizmo.hideAxis = {rotate:['e']}
  76. this.transformControls.setRotateMethod(2)
  77. //右屏
  78. this.transformControls2 = new TransformControls(viewer.mainViewport.camera, viewer.renderArea,{
  79. dontHideWhenFaceCamera: true,
  80. });
  81. this.transformControls.setSize(1.5)
  82. viewer.scene.scene.add(this.transformControls2)
  83. Potree.Utils.setObjectLayers(this.transformControls2, 'layer2' )
  84. let mouseDown = (e)=>{
  85. viewer.outlinePass.edgeStrength = 0//暂时消失线
  86. }
  87. let mouseUp = (e)=>{
  88. //this.updateEdgeStrength()
  89. viewer.outlinePass.edgeStrength = oriEdgeStrength
  90. }
  91. this.transformControls.addEventListener('mouseDown',mouseDown)
  92. this.transformControls2.addEventListener('mouseDown',mouseDown)
  93. this.transformControls.addEventListener('mouseUp',mouseUp)
  94. this.transformControls2.addEventListener('mouseUp',mouseUp)
  95. }
  96. {
  97. this.secondCompass = new Compass(null)
  98. }
  99. viewer.setControls(viewer.orbitControls)
  100. //viewer.mainViewport.view.fixZWhenPan = true
  101. viewer.orbitControls.constantlyForward = true
  102. viewer.addEventListener('global_single_click',(e)=>{
  103. if(
  104. this.noNeedSelection //如模型查看页
  105. || viewer.scene.cameraAnimations.some(c=>c.onUpdate) //正在播放
  106. || e.drag && e.drag.notPressMouse //在加测量线
  107. || viewer.mainViewport.view.isFlying() //有其他校准
  108. || this.split //分屏中
  109. || e.clickElement //触发别的点击事件,如测量时click marker /* && e.clickElement != e.intersect.object */
  110. ){
  111. return
  112. }
  113. if(e.intersect){
  114. let object = e.intersect.object || e.intersect.pointcloud
  115. let objects = this.getAllObjects()
  116. if(objects.includes(object)){
  117. this.selectModel(object)
  118. }else{
  119. //if(!viewer.inputHandler.selection[0]){//正在平移和旋转,不允许取消
  120. this.selectModel(null)
  121. //}
  122. }
  123. }else{
  124. //if(!viewer.inputHandler.selection[0]){
  125. this.selectModel(null)
  126. //}
  127. }
  128. })
  129. viewer.inputHandler.addEventListener('keydown', (e)=>{
  130. if((e.event.key).toLowerCase() == "h" ){
  131. this.fadeOutlineAuto = !this.fadeOutlineAuto
  132. this.showModelOutline(this.selected,!!this.selected)
  133. }
  134. })
  135. viewer.ssaaRenderPass.enabled = false
  136. viewer.outlinePass.enabled = true
  137. //Potree.settings.intersectWhenHover = false
  138. //Potree.Utils.updateVisible(viewer.reticule, 'force', false)
  139. viewer.mainViewport.camera.near = 0.05; // too small will result in z-fighting
  140. viewer.addEventListener('updateModelBound', (e)=>{
  141. if(this.split){
  142. this.SplitScreen.updateCameraOutOfModel(/* this.selected && [this.selected] */)
  143. }
  144. })
  145. {//校准页面拖拽
  146. //左右屏都可以拖拽模型,旋转只能左屏
  147. let dragInfo
  148. let drag = (e)=>{
  149. if(this.split && this.selected && this.transformState && (e.dragViewport.name == 'top' || this.transformState == 'translate') ){
  150. if(e.type == 'global_mousedown' ){ //开始
  151. //if((e.intersect.object || e.intersect.pointcloud) == this.selected){
  152. if(e.intersect.pointclouds.includes(this.selected) || e.intersect.allElements.some(e=>e.object == this.selected)){
  153. dragInfo = {}
  154. //if(this.selected.isPointcloud){
  155. viewer.outlinePass.edgeStrength = 0//暂时消失线
  156. //}
  157. }
  158. }
  159. if(e.type == 'global_drag' && dragInfo ){
  160. if(this.transformState == 'translate'){
  161. let moveVec = Potree.Utils.getOrthoCameraMoveVec(e.drag.pointerDelta, e.dragViewport.camera )//最近一次移动向量
  162. this.selected.position.add(moveVec)
  163. this.selected.dispatchEvent("position_changed")
  164. }else if(this.transformState == 'rotate'){
  165. let vec = new THREE.Vector3().subVectors(e.intersect.orthoIntersect || e.intersect.location, this.selected.boundCenter).setZ(0)
  166. if(dragInfo.lastVec == void 0){//global_mousedown
  167. dragInfo.lastVec = vec
  168. return
  169. }
  170. let angle = math.getAngle(dragInfo.lastVec, vec, 'z')
  171. dragInfo.lastVec = vec
  172. //this.selected.rotation.z += angle //局部
  173. /* object.quaternion.copy( .setFromAxisAngle( new THREE.Vector3(0,0,1), angle ) );
  174. object.quaternion.multiply( quaternionStart ).normalize(); */
  175. let diffQua = new THREE.Quaternion().setFromAxisAngle( new THREE.Vector3(0,0,1), angle )
  176. this.selected.quaternion.premultiply(diffQua) //世界
  177. this.selected.dispatchEvent("rotation_changed")
  178. }
  179. return {stopContinue:true}
  180. }
  181. }
  182. }
  183. viewer.addEventListener('global_mousedown', drag)
  184. viewer.addEventListener('global_drag', drag, 10)
  185. viewer.addEventListener('global_mousemove', (e)=>{
  186. if(this.split && this.transformState && !e.drag && (e.hoverViewport.name == 'top' || this.transformState == 'translate')){
  187. /* if(this.lastHoverViewport != e.hoverViewport){
  188. this.lastHoverViewport = e.hoverViewport
  189. this.transformControls.view = e.hoverViewport.view
  190. this.transformControls.camera = e.hoverViewport.camera
  191. this.transformControls.hideAxis( this.transformState, e.hoverViewport.name == 'top' ? [z] : [x,y]);
  192. } */
  193. let mouseover = e.intersect.pointclouds.includes(this.selected) || e.intersect.allElements.some(e=>e.object == this.selected)
  194. //let mouseover = (e.intersect.object || e.intersect.pointcloud) == this.selected
  195. if(mouseover){
  196. if(this.transformState == 'translate'){
  197. viewer.dispatchEvent({
  198. type : "CursorChange", action : "add", name:"movePointcloud"
  199. })
  200. }else{
  201. viewer.dispatchEvent({
  202. type : "CursorChange", action : "add", name:"rotatePointcloud"
  203. })
  204. }
  205. }else{
  206. this.clearTranCursor()
  207. }
  208. }
  209. })
  210. viewer.addEventListener('global_drop', (e)=>{
  211. dragInfo = null
  212. this.clearTranCursor()
  213. //this.updateEdgeStrength()
  214. viewer.outlinePass.edgeStrength = oriEdgeStrength
  215. })
  216. }
  217. /* viewer.addEventListener('background_changed',()=>{
  218. }) */
  219. },
  220. clearTranCursor(){
  221. viewer.dispatchEvent({
  222. type : "CursorChange", action : "remove", name:"movePointcloud"
  223. })
  224. viewer.dispatchEvent({
  225. type : "CursorChange", action : "remove", name:"rotatePointcloud"
  226. })
  227. },
  228. enterSplit(){
  229. this.split = true
  230. if(this.selected) this.SplitScreen.focusCenter = this.selected.boundCenter //旋转中心。注意 boundCenter不能直接赋值,否则改变后focusCenter也要改
  231. else this.SplitScreen.focusCenter = null
  232. this.SplitScreen.splitStart(viewportProps)
  233. this.beforeSplit = {
  234. pointDensity: Potree.settings.pointDensity,
  235. }
  236. Potree.settings.pointDensity = 'fourViewports' //强制降低点云质量
  237. viewer.setControls(viewer.fpControls)
  238. let rightViewport = viewer.viewports.find(e=>e.name == 'right')
  239. let topViewport = viewer.viewports.find(e=>e.name == 'top')
  240. topViewport.alignment = true
  241. rightViewport.rotateSide = true
  242. rightViewport.skyboxFixPos = true
  243. rightViewport.skyboxMinZoom = 10
  244. rightViewport.skyboxRenderFun = ()=>{// 使cube的一面永远正向镜头。 因侧视图的camera是ortho类型,需要平视mesh才不会拉伸
  245. viewer.skybox.scene.children[0].rotation.copy(rightViewport.camera.rotation)
  246. }
  247. topViewport.skyboxRenderFun = ()=>{
  248. viewer.skybox.scene.children[0].rotation.set(0,0,0)
  249. }
  250. viewer.viewports[1].layersAdd('layer2')
  251. viewer.viewports[0].layersAdd('layer1')
  252. Potree.Utils.setObjectLayers(this.transformControls, 'layer1' )
  253. this.transformControls.view = viewer.viewports[0].view
  254. this.transformControls.camera = viewer.viewports[0].camera
  255. this.transformControls._gizmo.hideAxis = {translate:['z'], rotate:['x','y','z'] }
  256. this.transformControls2.view = viewer.viewports[1].view
  257. this.transformControls2.camera = viewer.viewports[1].camera
  258. this.transformControls2._gizmo.hideAxis = {translate:['x','y'], rotate:['x','y','z'] }
  259. this.secondCompass.changeViewport(viewer.viewports[0])
  260. this.secondCompass.setDomPos()
  261. this.secondCompass.setDisplay(true)
  262. viewer.compass.changeViewport(viewer.viewports[1])
  263. viewer.compass.setDomPos()
  264. //this.changeSkyboxGeo(true)
  265. },
  266. leaveSplit(){
  267. this.split = false
  268. this.SplitScreen.unSplit()
  269. viewer.setControls(viewer.orbitControls)
  270. Potree.settings.pointDensity = this.beforeSplit.pointDensity
  271. /* if(this.selected && this.selected.isPointcloud){
  272. this.showModelOutline(this.selected, true)
  273. this.selected.material.activeAttributeName = "rgba"
  274. } */
  275. this.transformControls.camera = viewer.viewports[0].camera
  276. this.transformControls.view = viewer.viewports[0].view
  277. this.transformControls._gizmo.hideAxis = {rotate:['e']}
  278. Potree.Utils.setObjectLayers(this.transformControls, 'sceneObjects' ) //恢复
  279. viewer.compass.changeViewport(viewer.viewports[0]) //恢复
  280. viewer.compass.setDomPos()
  281. this.secondCompass.setDisplay(false)
  282. },
  283. rotateSideCamera(angle){
  284. this.SplitScreen.rotateSideCamera(viewer.viewports.find(e=>e.name == 'right'), angle)
  285. },
  286. setTransformState(state){//校准时
  287. this.transformState = state
  288. this.clearTranCursor()
  289. },
  290. //---------------------------
  291. /* writeToHistory(content){
  292. if(!this.prepareRecord)return;
  293. this.prepareRecord = false
  294. this.history.push(content)
  295. }, */
  296. //---------------------------
  297. getAllObjects(){
  298. return viewer.objs.children.concat(viewer.scene.pointclouds)
  299. },
  300. getModel(id){
  301. let models = this.getAllObjects()
  302. return models.find(e=>e.dataset_id == id)
  303. },
  304. removeModel(model){
  305. if(this.selected == model) this.selectModel(null)
  306. let dispose = (e)=>{
  307. e.geometry && e.geometry.dispose()
  308. e.material && e.material.dispose()
  309. }
  310. if(model.isPointcloud){
  311. dispose(model)
  312. viewer.scene.removePointCloud(model)
  313. }else{
  314. model.traverse(e=>{
  315. dispose(e)
  316. })
  317. viewer.objs.remove(model)
  318. }
  319. },
  320. selectModel(model, state=true, fitBound, by2d){
  321. if(!model) {
  322. model = this.selected
  323. state = false
  324. }
  325. if(state){
  326. if(this.selected){
  327. if(this.selected == model) return
  328. else{
  329. let transToolAttached = !!this.transformControls.object
  330. this.selectModel(this.selected, false, fitBound, by2d)
  331. transToolAttached && this.transformControls.attach(model)
  332. }
  333. }
  334. this.selected = model
  335. MergeEditor.focusOn(model, 500, !!fitBound) //通过在场景里点击模型的话,不focus
  336. this.showModelOutline(model)
  337. //this.updateEdgeStrength()
  338. //console.log('selectModel', model)
  339. }else{
  340. if(this.selected != model)return //model本来就没选中,不需要处理(防止2d先选中新的再取消旧的)
  341. this.showModelOutline(model, false)
  342. this.selected = null
  343. this.transformControls.detach() //viewer.transformObject(null);
  344. //console.log('selectModel', null)
  345. }
  346. if(!by2d && model){
  347. model.dispatchEvent({type:'changeSelect', selected : state})
  348. }
  349. },
  350. showModelOutline(model, state){
  351. if(this.fadeOutlineAuto){
  352. if(state === false){
  353. viewer.outlinePass.selectedObjects = []
  354. clearTimeout(this.timer)
  355. return
  356. }
  357. viewer.outlinePass.selectedObjects = [model]
  358. if(this.timer){
  359. clearTimeout(this.timer)
  360. }
  361. this.timer = setTimeout(()=>{
  362. viewer.outlinePass.selectedObjects = []
  363. }, 1000)
  364. }else{
  365. if(state === false){
  366. viewer.outlinePass.selectedObjects = []
  367. }else{
  368. viewer.outlinePass.selectedObjects = [model]
  369. }
  370. }
  371. },
  372. /*updateEdgeStrength(){
  373. if(!this.selected)return
  374. if(this.selected.isPointcloud){
  375. viewer.outlinePass.edgeStrength = edgeStrengths.pointcloud// / this.selected.material.opacity
  376. }else{
  377. viewer.outlinePass.edgeStrength = edgeStrengths.glb
  378. }
  379. },*/
  380. focusOn(objects, duration = 400, fitBound=true, dontLookUp){
  381. if(!(objects instanceof Array)){
  382. objects = [objects]
  383. }
  384. let boundingBox = new THREE.Box3
  385. objects.forEach(object=>{
  386. boundingBox.union(object.boundingBox.clone().applyMatrix4(object.matrixWorld))
  387. })
  388. if(fitBound){
  389. viewer.focusOnObject({boundingBox}, 'boundingBox', duration, {dontLookUp, dontChangeCamDir:true})
  390. }else{
  391. /*
  392. let position = viewer.inputHandler.intersect ? viewer.inputHandler.intersect.location : boundingBox.getCenter(new THREE.Vector3)
  393. position && viewer.focusOnObject({position}, 'point', duration, {dontChangePos: true})
  394. */
  395. let position = viewer.inputHandler.intersect ? viewer.inputHandler.intersect.location : boundingBox.getCenter(new THREE.Vector3)
  396. if(!position)return
  397. /* let targetOld = viewer.mainViewport.view.getPivot()
  398. let projected1 = targetOld.clone().project(viewer.mainViewport.camera);
  399. let projected2 = position.clone().project(viewer.mainViewport.camera); //使用其z
  400. let targetNew = projected1.clone().setZ(projected2.z).unproject(viewer.mainViewport.camera);
  401. viewer.mainViewport.view.lookAt(targetNew) */
  402. viewer.mainViewport.view.radius = viewer.mainViewport.camera.position.distanceTo(position)
  403. //为了不改画面,不调节方向了,只能调调radius,一定程度将target靠近model
  404. }
  405. },
  406. moveBoundCenterTo(model,pos){ //使boundCenter在所要的位置
  407. let diff = new THREE.Vector3().subVectors(pos, model.boundCenter)
  408. model.position.add(diff);
  409. },
  410. getBoundCenter(model){
  411. if(!model.boundCenter) model.boundCenter = new THREE.Vector3
  412. model.boundingBox.getCenter(model.boundCenter).applyMatrix4(model.matrixWorld)
  413. },
  414. setModelBtmHeight(model, z ){
  415. //无论模型怎么缩放、旋转,都使最低点为z
  416. if(z == void 0) z = model.btmHeight; //维持离地高度
  417. else model.btmHeight = z;
  418. model.updateMatrixWorld()
  419. let boundingBox2 = model.boundingBox.clone().applyMatrix4(model.matrixWorld)
  420. let size = boundingBox2.getSize(new THREE.Vector3);
  421. let center = boundingBox2.getCenter(new THREE.Vector3);
  422. let hopeZ = z + size.z / 2
  423. //model.position.z = z + size.z / 2 - center.z
  424. model.position.z += (hopeZ - center.z)
  425. },
  426. computeBtmHeight(model){ //位移之后重新计算btmHeight
  427. model.updateMatrixWorld()
  428. let boundingBox2 = model.boundingBox.clone().applyMatrix4(model.matrixWorld)
  429. let size = boundingBox2.getSize(new THREE.Vector3);
  430. let center = boundingBox2.getCenter(new THREE.Vector3);
  431. model.btmHeight = center.z - size.z / 2
  432. },
  433. maintainBoundXY(model){ //在旋转和缩放后,立即执行这个函数,使boundCenter保持原位
  434. model.updateMatrixWorld()
  435. let center1 = model.boundCenter.clone();//还未更新的
  436. this.getBoundCenter(model)//更新
  437. let center2 = model.boundCenter.clone();
  438. let diff = new THREE.Vector2().subVectors(center1,center2);
  439. model.position.x += diff.x;
  440. model.position.y += diff.y;
  441. model.boundCenter.copy(center1)
  442. },
  443. maintainBoundCenter(model){
  444. model.updateMatrixWorld()
  445. let center1 = model.boundCenter.clone();//还未更新的
  446. this.getBoundCenter(model)//更新
  447. let center2 = model.boundCenter.clone();
  448. let diff = new THREE.Vector3().subVectors(center1,center2);
  449. model.position.add(diff)
  450. model.boundCenter.copy(center1)
  451. },
  452. modelTransformCallback(model){
  453. model.updateMatrixWorld()
  454. if(model.matrixWorld.equals(model.lastMatrixWorld))return
  455. viewer.scene.measurements.forEach(measure=>{
  456. let changed
  457. measure.points_datasets.forEach((dataset_id,i)=>{
  458. if(dataset_id == model.dataset_id){
  459. changed = true
  460. measure.points[i] = Potree.Utils.datasetPosTransform({fromDataset:true,datasetId:dataset_id, position:measure.dataset_points[i].clone()})
  461. measure.updateMarker(measure.markers[i], measure.points[i])
  462. }
  463. })
  464. if(changed){//仿transformByPointcloud
  465. measure.getPoint2dInfo(measure.points)
  466. measure.update()
  467. measure.setSelected(false)//隐藏edgelabel
  468. }
  469. })
  470. model.lastMatrixWorld = model.matrixWorld.clone()
  471. },
  472. changeOpacity(model, opacity){
  473. let isRoot = model.dataset_id != void 0 //是否是最外层
  474. if(model.isPointcloud){
  475. model.changePointOpacity(opacity)
  476. //MergeEditor.updateEdgeStrength()
  477. }else{
  478. //model.traverse(e=>e.material && setOp(e, opacity))
  479. model.traverse(mesh=>{
  480. if(mesh.material){
  481. mesh.material.opacity = opacity
  482. if(opacity<1){
  483. mesh.material.transparent = true
  484. if(model.isPointcloud){
  485. mesh.changePointOpacity(opacity)
  486. }else{
  487. mesh.material.opacity = opacity
  488. }
  489. mesh.renderOrder = Potree.config.renderOrders.model+1
  490. mesh.material.depthWrite = false
  491. }else{
  492. mesh.material.transparent = false
  493. mesh.renderOrder = Potree.config.renderOrders.model
  494. mesh.material.depthWrite = true
  495. }
  496. }
  497. })
  498. }
  499. isRoot && (model.opacity = opacity)//记录在最外层
  500. }
  501. }
  502. export default MergeEditor
  503. /*
  504. note:
  505. 要注意getHoveredElements只在getIntersect时才使interactables包含加载的model, 也就是model上不能有使之成为interactables的事件,否则在鼠标hover到模型上开始转动的一瞬间很卡。
  506. */