Overlay.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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. }
  39. setContent(type, src, autoSize){
  40. this.mediaType = type
  41. let loadDone = ()=>{
  42. autoSize && this.autoSize()
  43. this.plane.material.uniforms.color.value = new THREE.Color('#fff')
  44. this.plane.material.opacity = 1
  45. }
  46. if(type == 'photo'){
  47. this.plane.material.map = texLoader.load(src, loadDone)
  48. }else{
  49. var video = videoPlayer.getVideo(src,this)
  50. this.addEventListener('loadedmetadata', loadDone)
  51. /* var video = $(`<video controls="controls" loop x5-playsinline="" webkit-playsinline="true" playsinline="true" controlslist="nodownload" preload="meta" ></video>`)[0]
  52. video.setAttribute("crossOrigin", 'Anonymous')//要在src设置好前解决跨域
  53. video.src = src
  54. video.onloadeddata = loadDone */
  55. video.play()
  56. this.plane.material.map = new THREE.VideoTexture(video)
  57. Potree.Common.mobileAutoPlay(video, ()=>{
  58. if(!this.disposed){
  59. video.play()
  60. }
  61. })
  62. }
  63. }
  64. autoSize(){//根据素材改变长宽
  65. let size = this.getMediaSize()
  66. if(size.x > 0 && size.y > 0){
  67. let area = this.plane.scale.x * this.plane.scale.y
  68. let r = Math.sqrt(area / (size.x * size.y))
  69. this.scale.x = size.x * r
  70. this.scale.y = size.y * r
  71. }
  72. this.dispatchEvent('scale_changed')
  73. }
  74. getMediaSize(){
  75. let size = new THREE.Vector2;
  76. let media = this.plane.material.map.image
  77. if(media){
  78. if(this.mediaType == 'photo'){
  79. size.x = media.width;
  80. size.y = media.height;
  81. }else{
  82. size.x = media.videoWidth
  83. size.y = media.videoHeight
  84. }
  85. }
  86. return size
  87. }
  88. dispose(){
  89. //geo和mat已经在mergeEditor里删了,这要删一下video啥的吗?
  90. let index = viewer.scene.overlays.indexOf(this)
  91. if(index == -1)return
  92. viewer.scene.overlays.splice(index,1)
  93. if(this.mediaType == 'video'){
  94. let media = this.plane.material.map.image
  95. media?.pause()
  96. this.disposed = true
  97. }
  98. }
  99. videoControl(state){
  100. var video = this.plane.material.map.image
  101. if(!video)return
  102. this.shouldPlay = state
  103. if (!state || state == 'stop') {
  104. if (!video.paused){
  105. video.pause()
  106. console.log('videoControl paused ')
  107. }
  108. }else if(state) {
  109. if (video.paused){
  110. console.log('videoControl play ')
  111. //video = this.loadVideo()
  112. video.play()
  113. }
  114. }
  115. }
  116. static updatePlayInSight(){
  117. const min = 0.15//最小可播放尺寸(屏幕宽高都是2)
  118. let camera = viewer.mainViewport.camera
  119. let camDir = viewer.mainViewport.view.direction
  120. let frustumMatrix = new THREE.Matrix4
  121. frustumMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse)
  122. let frustum = new THREE.Frustum();
  123. frustum.setFromProjectionMatrix(frustumMatrix)
  124. let insight = (overlay)=>{
  125. if(overlay.plane.material.side!=2){ //side为0
  126. let dir = overlay.plane.getWorldDirection(new THREE.Vector3)
  127. if(dir.dot(camDir)>0 ){
  128. console.log('dir.dot(camDir)',dir.dot(camDir))
  129. return false
  130. }
  131. //可能看到背面。若能看到正面,视线方向和plane朝向必定为钝角
  132. }
  133. let bound = overlay.bound.clone()
  134. let insight = frustum.intersectsBox(bound )
  135. if(!insight)return false
  136. bound.applyMatrix4(frustumMatrix); //project on screen
  137. let boundSize = bound.getSize(new THREE.Vector3)
  138. if(boundSize.x < min && boundSize.y < min){
  139. //console.log('too small', boundSize)
  140. return false
  141. }
  142. return true
  143. }
  144. viewer.scene.overlays.forEach(overlay=>{
  145. if(overlay.mediaType != 'video')return
  146. let shouldPlay = overlay.realVisible() && insight(overlay)
  147. overlay.videoControl(shouldPlay)
  148. })
  149. }
  150. }