|
|
@@ -4,7 +4,7 @@ import * as THREE from "../../../libs/three.js/build/three.module.js";
|
|
|
import BasicMaterial from '../materials/BasicMaterial.js'
|
|
|
|
|
|
import {TextSprite} from "./TextSprite.js";
|
|
|
-
|
|
|
+//import DepthBasicMaterial from "../materials/DepthBasicMaterial.js";
|
|
|
import math from '@sdk/utils/math'
|
|
|
/* import SecurityCamera from '../core/cameras/SecurityCamera'
|
|
|
import SecurityControls from '../core/controls/SecurityControls' */
|
|
|
@@ -27,15 +27,17 @@ const vec1 = new THREE.Vector3(),
|
|
|
vec3 = new THREE.Vector3(),
|
|
|
quat1 = new THREE.Quaternion(),
|
|
|
quat2 = new THREE.Quaternion()
|
|
|
-let cameraModel
|
|
|
+let cameraModel, loadingCamModel
|
|
|
+
|
|
|
|
|
|
+//测试场景: http://192.168.0.25/mix3d/#/home/671 潘少 Aa123456 http://192.168.0.25/epg.html?m=YZL-jm-lrZcWxzPaPJ#/tag
|
|
|
|
|
|
|
|
|
//接收4dkk的监控 暂不支持修改 可以直接加到模型上,注意所附模型旋转90度后角度才对。
|
|
|
export default class Monitor extends THREE.Object3D{
|
|
|
constructor(data, model){
|
|
|
super()
|
|
|
-
|
|
|
+ this.isMonitor = true
|
|
|
warnHls()
|
|
|
|
|
|
data.video = testUrl
|
|
|
@@ -52,7 +54,8 @@ export default class Monitor extends THREE.Object3D{
|
|
|
model.add(this)
|
|
|
|
|
|
|
|
|
- this.video = videoPlayer.getVideo(data.video,this)
|
|
|
+ let videoUrl = this.getVideoSrc()
|
|
|
+ this.video = videoPlayer.getVideo(videoUrl ,this)
|
|
|
if (data.video) {
|
|
|
//console.error('createVideo', this.videoSrc, this.sid)
|
|
|
/* this.video.onloadedmetadata = () => {
|
|
|
@@ -74,12 +77,12 @@ export default class Monitor extends THREE.Object3D{
|
|
|
this.addEventListener('loadedmetadata', canPlayed)
|
|
|
}
|
|
|
|
|
|
- if (Hls.isSupported() && data.videoType !== 2) {
|
|
|
+ if (Hls.isSupported() && data.urlType == 1) {
|
|
|
//似乎Hls不支持就无法播放
|
|
|
let hls = new Hls()
|
|
|
- hls.loadSource(data.video)
|
|
|
+ hls.loadSource(videoUrl)
|
|
|
hls.attachMedia(this.video)
|
|
|
- hls.on(Hls.Events.ERROR, (event, data) => console.log('HLS加载失败', event, data))
|
|
|
+ hls.on(Hls.Events.ERROR, (event, data) =>{ console.log('HLS加载失败', data.name, event, data)})
|
|
|
this.hlsVideoPlayer = hls
|
|
|
}
|
|
|
this.play() // ios需要
|
|
|
@@ -98,7 +101,9 @@ export default class Monitor extends THREE.Object3D{
|
|
|
opacity: 0.1,
|
|
|
side: THREE.DoubleSide,
|
|
|
depthTest: false,
|
|
|
- })
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
// 监控视频材质
|
|
|
this.videoMat = new BasicMaterial({
|
|
|
map: new THREE.VideoTexture(this.video),
|
|
|
@@ -109,29 +114,32 @@ export default class Monitor extends THREE.Object3D{
|
|
|
})
|
|
|
// 摄像头
|
|
|
if (!cameraModel) {
|
|
|
- viewer.loadModel({fileType:'glb', url:`${Potree.resourcePath}/models/glb/monitor.glb`},(model)=>{
|
|
|
- console.log('load monitor glb')
|
|
|
- this.cameraModel = model.children[0].children[0]
|
|
|
- this.cameraModel.geometry.translate(30, 50, -10)
|
|
|
- this.cameraModel.quaternion.setFromEuler(new THREE.Euler(Math.PI / 2, Math.PI, 0))
|
|
|
- this.obj3d.add(this.cameraModel)
|
|
|
- model.parent.remove(model)
|
|
|
- cameraModel = this.cameraModel.clone()
|
|
|
- this.modelLoaded()
|
|
|
- })
|
|
|
- }else{
|
|
|
- this.cameraModel = cameraModel.clone()
|
|
|
- this.obj3d.add(this.cameraModel)
|
|
|
+ if(!loadingCamModel){
|
|
|
+ loadingCamModel = true
|
|
|
+ viewer.loadModel({fileType:'glb', url:`${Potree.resourcePath}/models/glb/monitor.glb`},(model)=>{
|
|
|
+ cameraModel = model.children[0].children[0]
|
|
|
+ cameraModel.geometry.translate(30, 50, -10)
|
|
|
+ cameraModel.quaternion.setFromEuler(new THREE.Euler(Math.PI / 2+0.24, Math.PI, 0))
|
|
|
+ cameraModel.name = 'cameraModel'
|
|
|
+ console.log('load monitor glb', cameraModel.uuid)
|
|
|
+ model.parent.remove(model)
|
|
|
+ viewer.scene.monitors.forEach(e=>e.modelLoaded())
|
|
|
+ loadingCamModel = false
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }else{
|
|
|
this.modelLoaded()
|
|
|
}
|
|
|
this.updateAspect()
|
|
|
|
|
|
- {
|
|
|
+ if(data.showTitle){
|
|
|
+ let group = new THREE.Shim.FollowRootObject(this) //透明有问题,只有放到overlayScene里渲染了
|
|
|
+
|
|
|
this.titleLabel = new TextSprite({
|
|
|
text: data.name,
|
|
|
backgroundColor: { r: 255, g: 255, b: 255, a: 0 },
|
|
|
textColor: { r: 255, g: 255, b: 255, a: 1 },
|
|
|
- textshadowColor: '#888',
|
|
|
+ textshadowColor: '#666',
|
|
|
borderRadius: 2,
|
|
|
fontsize: 34,
|
|
|
renderOrder: 5,
|
|
|
@@ -140,7 +148,9 @@ export default class Monitor extends THREE.Object3D{
|
|
|
})
|
|
|
this.titleLabel.sprite.material.depthTest = this.titleLabel.sprite.material.depthWrite = true
|
|
|
this.titleLabel.position.set(0, -0.2, 0.1)
|
|
|
- this.add(this.titleLabel)
|
|
|
+ group.add(this.titleLabel)
|
|
|
+ viewer.scene.overlayScene.add(group)
|
|
|
+ group.name = 'monitorLabel'
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -153,9 +163,9 @@ export default class Monitor extends THREE.Object3D{
|
|
|
this.position.copy(Potree.Utils.tran4dkkVecInModel(this.position, model))
|
|
|
|
|
|
// target的优先级大于rotation
|
|
|
- if (data.target) {
|
|
|
+ if (data.data.target) {
|
|
|
this.target = Potree.Utils.tran4dkkVecInModel(data.data.target, model)
|
|
|
- this.lookAt(data.target)
|
|
|
+ this.lookAt(data.data.target)
|
|
|
} else {
|
|
|
data.data.rotation && this.quaternion.setFromEuler(data.data.rotation)
|
|
|
this.target = new THREE.Vector3(0, 0, -1).applyQuaternion(this.quaternion).add(this.position)
|
|
|
@@ -164,12 +174,17 @@ export default class Monitor extends THREE.Object3D{
|
|
|
|
|
|
|
|
|
this.roll = 0
|
|
|
+
|
|
|
+
|
|
|
data.data.pitch && (this.pitch = data.data.pitch)
|
|
|
data.data.yaw && (this.yaw = data.data.yaw)
|
|
|
data.data.roll && this.setRoll(this.data.data.roll)
|
|
|
+
|
|
|
+ if(model.props.baseRotation?.x == 0){ //该模型已经矫正,无需旋转90度,但是场景的数据需要,导致monitor和模型不匹配,需要再旋转
|
|
|
+ this.quaternion.copy(Potree.math.convertQuaternion.YupToZup(this.quaternion))
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
|
|
|
|
|
|
//this.updateInfo(true)
|
|
|
@@ -193,11 +208,28 @@ export default class Monitor extends THREE.Object3D{
|
|
|
viewer.addEventListener('update', this.events.update )
|
|
|
|
|
|
window.monitor = this
|
|
|
- Potree.Utils.setObjectLayers(this,'monitor')
|
|
|
-
|
|
|
+ Potree.Utils.setObjectLayers(this,'dontIntersect')
|
|
|
+ Potree.Utils.setObjectLayers(this.cylinder.bottom,'monitor')
|
|
|
+ this.cameraModel && Potree.Utils.setObjectLayers(this.cameraModel,'sceneObjects')
|
|
|
}
|
|
|
|
|
|
- modelLoaded(){
|
|
|
+ getVideoSrc(){
|
|
|
+ if(this.data.urlType === 2){
|
|
|
+ let a = this.parent.props.raw.surveillancePath.split('/'); //用户上传的文件
|
|
|
+ a.pop()
|
|
|
+ return a.join('/') + '/' + this.data.fileName
|
|
|
+ }else{
|
|
|
+ return this.data.playUrl
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ modelLoaded(){
|
|
|
+ this.cameraModel = cameraModel.clone()
|
|
|
+ this.cameraModel.material = cameraModel.material.clone()
|
|
|
+ this.obj3d.add(this.cameraModel)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
this.cameraModel.addEventListener('mouseover',()=>{
|
|
|
CursorDeal.add('hoverMonitor')
|
|
|
this.highlight(true)
|
|
|
@@ -215,6 +247,14 @@ export default class Monitor extends THREE.Object3D{
|
|
|
|
|
|
|
|
|
watch(){
|
|
|
+
|
|
|
+ if (!this.videoActive){
|
|
|
+ console.log('monitorError src:', this.video.src)
|
|
|
+ return viewer.dispatchEvent('monitorError' )
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
let camera = viewer.mainViewport.camera
|
|
|
this.updateAspect()
|
|
|
this.isWatching = true
|
|
|
@@ -228,8 +268,9 @@ export default class Monitor extends THREE.Object3D{
|
|
|
this.showVideo(true)
|
|
|
this.video.pause()//先显示出画面
|
|
|
setTimeout(()=>{
|
|
|
- viewer.mainViewport.cameraLayers = ['monitor'] //hide others
|
|
|
- },1000)
|
|
|
+ viewer.mainViewport.cameraLayers = ['monitor'] //hide others
|
|
|
+ viewer.scene.monitors.forEach(e=>Potree.Utils.updateVisible(e,'watch', e == this ))
|
|
|
+ },800)
|
|
|
viewer.mainViewport.view.setRotMode('free')
|
|
|
viewer.mainViewport.view.setView({
|
|
|
position: this.getWorldPosition(new THREE.Vector3),
|
|
|
@@ -256,12 +297,13 @@ export default class Monitor extends THREE.Object3D{
|
|
|
this.cameraModel.material.color.copy(normalColor)
|
|
|
viewer.mainViewport.view.cancelFlying()
|
|
|
viewer.mainViewport.cameraLayers = null
|
|
|
+ viewer.scene.monitors.forEach(e=>Potree.Utils.updateVisible(e,'watch', true ))
|
|
|
this.video.pause()
|
|
|
viewer.mainViewport.view.setView({
|
|
|
position: this.oldState.position,
|
|
|
quaternion: this.oldState.quaternion,
|
|
|
|
|
|
- onUpdate:(percent)=>{
|
|
|
+ onUpdate:(percent)=>{
|
|
|
camera.fov = this.fov * (1-percent) + this.oldState.fov * percent
|
|
|
camera.updateProjectionMatrix()
|
|
|
},
|
|
|
@@ -281,7 +323,7 @@ export default class Monitor extends THREE.Object3D{
|
|
|
showVideo(isShow) {
|
|
|
//console.warn('showVideo', this.info.sid, isShow )
|
|
|
|
|
|
- if (!this.videoActive) return
|
|
|
+ if (!this.videoActive) return
|
|
|
|
|
|
if (isShow) {
|
|
|
/* if (browser.detectIOS()) {
|
|
|
@@ -364,7 +406,7 @@ export default class Monitor extends THREE.Object3D{
|
|
|
this.videoMat.dispose()
|
|
|
|
|
|
|
|
|
- this.titleLabel.dispose()
|
|
|
+ this.titleLabel?.dispose()
|
|
|
|
|
|
this.hlsVideoPlayer && this.hlsVideoPlayer.destroy()
|
|
|
|
|
|
@@ -466,24 +508,20 @@ export default class Monitor extends THREE.Object3D{
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 横滚角
|
|
|
- setRoll(angle) {
|
|
|
- this.roll = angle % 360
|
|
|
- this.obj3d.quaternion.setFromAxisAngle(vec1.set(0, 0, -1), THREE.MathUtils.degToRad(angle))
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- get yaw() {
|
|
|
- // 左右转角
|
|
|
- let lookAt = vec1.copy(this.cylinder.bottom.position).applyQuaternion(this.quaternion)
|
|
|
- let lookAtXZ = lookAt.setY(0)
|
|
|
- let frontDir = vec2.set(0, 0, 1)
|
|
|
- let frontCross = vec3.set(1, 0, 0)
|
|
|
- let angle = (THREE.MathUtils.radToDeg(lookAtXZ.angleTo(frontDir) * Math.sign(lookAtXZ.dot(frontCross))) + 180) % 360
|
|
|
- if (angle > 180) angle = angle - 360
|
|
|
+
|
|
|
+ set pitch(pitch) {
|
|
|
+ pitch = Math.min(Math.max(pitch, -89.9), 89.9) // 防止万向锁
|
|
|
|
|
|
- return angle
|
|
|
+ let yaw = this.yaw < 0 ? this.yaw + 360 : this.yaw
|
|
|
+ let upDir = vec1.set(0, 1, 0)
|
|
|
+ let rightDir = vec2.set(1, 0, 0) //.applyQuaternion(this.quaternion)
|
|
|
+ let yawQuat = quat1.setFromAxisAngle(upDir, THREE.MathUtils.degToRad(yaw))
|
|
|
+ let pitchQuat = quat2.setFromAxisAngle(rightDir, THREE.MathUtils.degToRad(pitch))
|
|
|
+ this.quaternion.multiplyQuaternions(yawQuat, pitchQuat)
|
|
|
+
|
|
|
+ //this.updateTarget()
|
|
|
}
|
|
|
+
|
|
|
|
|
|
set yaw(yaw) {
|
|
|
let pitch = this.pitch // 要先计算pitch,防止窜数据
|
|
|
@@ -495,29 +533,33 @@ export default class Monitor extends THREE.Object3D{
|
|
|
|
|
|
//this.updateTarget()
|
|
|
}
|
|
|
-
|
|
|
- get pitch() {
|
|
|
- // 上下转角
|
|
|
+
|
|
|
+ // 横滚角
|
|
|
+ setRoll(angle) {//因加在子物体上,非0时播放视频是歪的(4dkk也这样)
|
|
|
+ this.roll = angle % 360
|
|
|
+ this.obj3d.quaternion.setFromAxisAngle(vec1.set(0, 0, -1) , THREE.MathUtils.degToRad(angle))
|
|
|
+ }
|
|
|
+ get pitch() {// 上下转角
|
|
|
+ return this.data.data.pitch //xzw改
|
|
|
let lookAt = vec1.copy(this.cylinder.bottom.position).applyQuaternion(this.quaternion)
|
|
|
let projectVec = vec2.copy(lookAt).projectOnPlane(vec3.set(0, 1, 0))
|
|
|
let pitch = THREE.MathUtils.radToDeg(lookAt.angleTo(projectVec) * Math.sign(lookAt.y)) % 180
|
|
|
if (pitch > 90) pitch = 90 - pitch
|
|
|
|
|
|
return pitch
|
|
|
- }
|
|
|
-
|
|
|
- set pitch(pitch) {
|
|
|
- pitch = Math.min(Math.max(pitch, -89.9), 89.9) // 防止万向锁
|
|
|
+ }
|
|
|
|
|
|
- let yaw = this.yaw < 0 ? this.yaw + 360 : this.yaw
|
|
|
- let upDir = vec1.set(0, 1, 0)
|
|
|
- let rightDir = vec2.set(1, 0, 0) //.applyQuaternion(this.quaternion)
|
|
|
- let yawQuat = quat1.setFromAxisAngle(upDir, THREE.MathUtils.degToRad(yaw))
|
|
|
- let pitchQuat = quat2.setFromAxisAngle(rightDir, THREE.MathUtils.degToRad(pitch))
|
|
|
- this.quaternion.multiplyQuaternions(yawQuat, pitchQuat)
|
|
|
+ get yaw() {// 左右转角
|
|
|
+ return this.data.data.yaw //xzw改 原先的计算不对,0变180
|
|
|
+ let lookAt = vec1.copy(this.cylinder.bottom.position).applyQuaternion(this.quaternion)
|
|
|
+ let lookAtXZ = lookAt.setY(0)
|
|
|
+ let frontDir = vec2.set(0, 0, 1)
|
|
|
+ let frontCross = vec3.set(1, 0, 0)
|
|
|
+ let angle = (THREE.MathUtils.radToDeg(lookAtXZ.angleTo(frontDir) * Math.sign(lookAtXZ.dot(frontCross))) + 180) % 360
|
|
|
+ if (angle > 180) angle = angle - 360
|
|
|
|
|
|
- //this.updateTarget()
|
|
|
- }
|
|
|
+ return angle
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|