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