Overlay.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. import * as THREE from "../../../libs/three.js/build/three.module.js";
  2. import BasicMaterial from '../materials/BasicMaterial.js'
  3. const planeGeometry = new THREE.PlaneBufferGeometry(1,1)
  4. const height4dkk = 0.5 //4dkk的planeGeometry高度
  5. let texLoader = new THREE.TextureLoader()
  6. import FlvVideoPlayerBase from '../utils/media/FlvVideoPlayerBase'
  7. import H5VideoPlayerBase from '../utils/media/H5VideoPlayerBase'
  8. const videoPlayer = Potree.browser.nonsupportH5Video ? new FlvVideoPlayerBase() : new H5VideoPlayerBase()
  9. export default class Overlay extends THREE.Object3D {
  10. constructor(data){
  11. super()
  12. this.data = data
  13. var plane = new THREE.Mesh(
  14. planeGeometry,
  15. new BasicMaterial({
  16. color: '#00c8af',
  17. opacity: 0.2,
  18. transparent: !0,
  19. polygonOffset: true, //是否开启多边形偏移 //ie不开启时blank也不会闪烁
  20. polygonOffsetFactor: -0.9, //多边形偏移因子
  21. polygonOffsetUnits: -4.0, //多边形偏移单位
  22. })
  23. )
  24. this.add(plane)
  25. this.plane = plane
  26. this.setContent( data.media[0], data.url, data.isNew)
  27. //this.setScale(data.width, data.height)
  28. this.scale.set(data.width||1, data.height||1, 1) //需要把width转化一下吗,还是后端转化?
  29. data.reverse && (this.scale.x *= -1)
  30. this.addEventListener('dispose',this.dispose.bind(this))
  31. let updatePlayInSight = ()=>{
  32. Common.intervalTool.isWaiting('updatePlayInSight', ()=>{
  33. Overlay.updatePlayInSight()
  34. },500)
  35. }
  36. this.addEventListener('isVisible',updatePlayInSight)
  37. this.addEventListener('transformChanged',updatePlayInSight)
  38. Potree.Utils.setObjectLayers(this,'dontIntersect')
  39. }
  40. setContent(type, src, autoSize){
  41. this.mediaType = type
  42. let loadDone = ()=>{
  43. autoSize && this.autoSize()
  44. this.plane.material.uniforms.color.value = new THREE.Color('#fff')
  45. this.plane.material.opacity = 1
  46. }
  47. if(type == 'photo'){
  48. this.plane.material.map = texLoader.load(src, loadDone)
  49. }else{
  50. var video = videoPlayer.getVideo(src,this)
  51. this.addEventListener('loadedmetadata', loadDone)
  52. /* var video = $(`<video controls="controls" loop x5-playsinline="" webkit-playsinline="true" playsinline="true" controlslist="nodownload" preload="meta" ></video>`)[0]
  53. video.setAttribute("crossOrigin", 'Anonymous')//要在src设置好前解决跨域
  54. video.src = src
  55. video.onloadeddata = loadDone */
  56. video.play()
  57. this.plane.material.map = new THREE.VideoTexture(video)
  58. Potree.Common.mobileAutoPlay(video, ()=>{
  59. if(!this.disposed){
  60. video.play()
  61. }
  62. })
  63. }
  64. }
  65. autoSize(){//根据素材改变长宽
  66. let size = this.getMediaSize()
  67. if(size.x > 0 && size.y > 0){
  68. let area = this.plane.scale.x * this.plane.scale.y
  69. let r = Math.sqrt(area / (size.x * size.y))
  70. this.scale.x = size.x * r
  71. this.scale.y = size.y * r
  72. }
  73. this.dispatchEvent('scale_changed')
  74. }
  75. getMediaSize(){
  76. let size = new THREE.Vector2;
  77. let media = this.plane.material.map.image
  78. if(media){
  79. if(this.mediaType == 'photo'){
  80. size.x = media.width;
  81. size.y = media.height;
  82. }else{
  83. size.x = media.videoWidth
  84. size.y = media.videoHeight
  85. }
  86. }
  87. return size
  88. }
  89. dispose(){
  90. //geo和mat已经在mergeEditor里删了,这要删一下video啥的吗?
  91. let index = viewer.scene.overlays.indexOf(this)
  92. if(index == -1)return
  93. viewer.scene.overlays.splice(index,1)
  94. if(this.mediaType == 'video'){
  95. let media = this.plane.material.map.image
  96. media?.pause()
  97. this.disposed = true
  98. }
  99. }
  100. videoControl(state){
  101. var video = this.plane.material.map.image
  102. if(!video)return
  103. this.shouldPlay = state
  104. if (!state || state == 'stop') {
  105. if (!video.paused){
  106. video.pause()
  107. //console.log('videoControl paused ')
  108. }
  109. }else if(state) {
  110. if (video.paused){
  111. //console.log('videoControl play ')
  112. //video = this.loadVideo()
  113. video.play()
  114. }
  115. }
  116. }
  117. static updatePlayInSight(){
  118. const min = 0.15//最小可播放尺寸(屏幕宽高都是2)
  119. let camera = viewer.mainViewport.camera
  120. let camDir = viewer.mainViewport.view.direction
  121. let frustumMatrix = new THREE.Matrix4
  122. frustumMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse)
  123. let frustum = new THREE.Frustum();
  124. frustum.setFromProjectionMatrix(frustumMatrix)
  125. let insight = (overlay)=>{
  126. if(overlay.plane.material.side!=2){ //side为0
  127. let dir = overlay.plane.getWorldDirection(new THREE.Vector3)
  128. if(dir.dot(camDir)>0 ){
  129. //console.log('dir.dot(camDir)',dir.dot(camDir))
  130. return false
  131. }
  132. //可能看到背面。若能看到正面,视线方向和plane朝向必定为钝角
  133. }
  134. let bound = overlay.bound.clone()
  135. let insight = frustum.intersectsBox(bound )
  136. if(!insight)return false
  137. bound.applyMatrix4(frustumMatrix); //project on screen
  138. let boundSize = bound.getSize(new THREE.Vector3)
  139. if(boundSize.x < min && boundSize.y < min){
  140. //console.log('too small', boundSize)
  141. return false
  142. }
  143. return true
  144. }
  145. viewer.scene.overlays.forEach(overlay=>{
  146. if(overlay.mediaType != 'video')return
  147. let shouldPlay = overlay.realVisible() && insight(overlay)
  148. overlay.videoControl(shouldPlay)
  149. })
  150. }
  151. }