<template src="./webgl_rxdz_vr.html">

</template>
<script>
	import * as THREE from 'three';
	import Stats from 'three/addons/libs/stats.module.js';
	import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
	import { DragControls } from 'three/addons/controls/DragControls.js';
	import {getStorage} from '@/utils/localStorage';
	import { Toast } from 'mint-ui';
	import { Range } from 'mint-ui';
	var requestId = "";
	const util = require('@/utils/util.js').default;
	import viewAI from '@/components/newBottomCom/viewAI/viewAI.vue';

	import commonPageMethod from '@/mixins/commonPageMethod.js';
	// import commonPageMethod from '@/common/commonPageMethod.js';
	export default {
		components: {
			viewAI
		},
		mixins: [commonPageMethod],
		/**
		 * 页面的初始数据
		 */
		data() {
			return {
				pvCurPageName: "add_AI_people",
				locusBehaviorName: "添加数字人",
				pvCurPageParams: null,
				houseId: "",
				pvId: 'p_2cmina_23080402',
				canvas: null,
				navbar: {
					showCapsule: 1,
					title: '添加数字人',
					titleColor: '#000',
					navPadding: 0,
					navPaddingBg: 'transparent',
					navBarColor: 'transparent',
					navBackColor: 'transparent',
					haveCallback: true, // 如果是 true 会接手 navbarBackClk
					fromShare: false,
					fromProject: 0,
					shareToken: "",
					pageName: this.pvCurPageName,
				},
				id: '', // 户型编号
				loader: null,
				scene: null,
				camera: null,
				// controlStarPosition: {
				// 	x: 0,
				// 	y: -5,
				// 	z: 0
				// }, //控制器初始位置
				cameraStarPosition: {
					x: 0,
					y: 0,
					z: 5
				}, //摄像头初始位置
				cameraLastPosition: null, //摄像头上一次移动到的位置
				controlLastPosition: null, //观察点上一次移动到的位置
				canvasHeight: 408, //canvas视图的高度-计算得出
				myLoadingStatus: false,
				repeatFlag: false, //重复点击
				isIOS: false,
				muted: true,
				hasOneTouch: false,
				rangeValue:50,
			}
		},
		beforeDestroy() {
			cancelAnimationFrame(requestId, this.canvas)
			this.worker && this.worker.terminate()
			if (this.renderer instanceof THREE.WebGLRenderer) {
				// 遍历场景中的所有子对象，找到类型为Mesh的对象并移除
				let deleList = this.scene.children.filter(object => {
					if (object instanceof THREE.Mesh) {
						return object
					}
				})
				if (deleList && deleList.length > 0) {
					this.scene.remove(...deleList);
				}
				this.scene.traverse(function(object) {
					if (object instanceof THREE.Mesh) {
						if (object.geometry && typeof(object.geometry.dispose) == 'function') {
							object.geometry.dispose();
						}
						if (object.material && typeof(object.material.dispose) == 'function') {
							object.material.dispose();
						}
						if (object.texture && typeof(object.texture.dispose) == 'function') {
							object.texture.dispose();
						}
					}
				});
				this.renderer.clear();
				this.renderer.dispose();
				this.renderer.forceContextLoss();
				this.renderer.context = null;
				this.renderer.domElement = null;
				this.renderer = null;;
			}
			console.warn("***beforeDestroy-webgl_rxdz_vr***");
		},
		mounted(options) {
			var that = this;
			console.warn("***webgl_rxdz_roam-options***", this.$route.query)
			this.isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
			this.videoUrl = this.$route.query.videoUrl || '';
			this.bgUrl = this.$route.query.bgUrl || 'https://elab-marketing-web.oss-accelerate.aliyuncs.com/replicate_images/1702457671501.png';
			
			// alert("***mounted-webgl_rxdz_roam***"+this.isIOS + this.curHouseObj)
			let screenWidth = window.screen.width;
			let screenHeight = window.screen.height;
			if (window.innerWidth && window.screen.width) {
				screenWidth = Math.min(window.innerWidth, window.screen.width)
			}
			if (window.innerHeight && window.screen.height) {
				screenHeight = Math.min(window.innerHeight, window.screen.height)
			}
			let unit = screenWidth / 750; //单位rpm 对应 px 的值
			// this.canvasHeight = screenHeight - (600 * unit) + (40 * unit);
			this.canvasHeight = screenWidth;
			this.houseId = this.$route.query.houseId ? this.$route.query.houseId : '';
			this.spaceId = this.$route.query.spaceId ? this.$route.query.spaceId : '';
			let container = this.$refs.webgl;
			let canvas3d = this.canvas = this.$refs.glcanvas;
			//uniapp 兼容写法，因为uni的页面对象的Vue 实例是$vm

			let camera = null,
				renderer = null;
			let needRender = false; //是否需要渲染 false表示不需要渲染；true 表示需要渲染
			let scene = this.scene = new THREE.Scene();
			let controls = null,
				boundary = null;
			let stats;
			let dragControls = null;
			let videoMesh = null;
			// let lineMesh = null;
			let radius = 50;	//全景图半径-全景图是个球体
			let fingerCount = 0;
			let lastPosition = new THREE.Vector3(0, -20, -27.49);
			let boundingBox = null;
			init();
			// this.clearEvent = clearEvent;
			// this.attendEvent = attendEvent;
			this.starRender = starRender; //对外暴露启动渲染的方法
			this.stopRender = stopRender; //对外暴露停止渲染的方法
			this.videoHandle = videoHandle;	//视频处理方法
			this.getVideoPosition = getVideoPosition;	//获取视频位置信息
			this.getVideoScale = getVideoScale;	//获取视频缩放数据
			this.videoMeshChange = videoMeshChange;	//数字人缩放方法
			if(window.__wxjs_environment === 'miniprogram'){
				this.navbar.showCapsule = 0;
			}
			function init() {
				// 创建相机位置
				camera = new THREE.PerspectiveCamera(90, screenWidth / that.canvasHeight, 0.1, 10000);
				// camera.up.set(0, 1, 0);//俯视状态，将相机的up向量设置为z轴负方向 {x:0,y:1,z:0}
				camera.position.set(that.cameraStarPosition.x, that.cameraStarPosition.y, that.cameraStarPosition.z);
				scene.add(camera);
				that.camera = camera;
				
				//加载环境720贴图
				// const loader = new THREE.TextureLoader();
				// const texture = loader.load(that.bgUrl, () => {
				// 	const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);
				// 	rt.fromEquirectangularTexture(renderer, texture);
				// 	scene.background = rt.texture;
				// });
				makeShaderCube();
				//antialias 这个值得设置为false，不然IOS上截图会失效
				renderer = that.renderer = new THREE.WebGLRenderer({
					canvas: canvas3d,
					alpha: true,
				});
				renderer.setPixelRatio(window.devicePixelRatio);
				renderer.setSize(screenWidth, that.canvasHeight);
				container.appendChild(renderer.domElement);

				controls = new OrbitControls(camera, renderer.domElement);
				controls.enableDamping = true; //启动缓动
				controls.minDistance = 0.0001;
				controls.maxDistance = radius - 10;
				// controls.minPolarAngle = 0; // 默认0
				// controls.maxPolarAngle = Math.PI / 2; // 默认Math.PI，即可以向下旋转到的视角。
				controls.enableZoom = true; //启用/禁用摄像机的缩放
				controls.enablePan = false; //启用/禁用摄像机平移
				controls.enableRotate = true; //启用/禁用摄像机水平或垂直旋转
				
				// 创建一个球体几何体
				var sphereGeometry = new THREE.SphereGeometry(radius, 60, 40);
				var sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
				var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
				sphere.position.set(0,0,0);
				sphere.geometry.computeBoundingBox();

				// 计算球体的包围盒
				boundingBox = new THREE.Box3().copy(sphere.geometry.boundingBox).applyMatrix4( sphere.matrixWorld);
				// 监听相机移动事件-限制只能在当前空间范围内移动
				controls.addEventListener('change', () => {
					// 检查相机位置是否超出边界框
					if (boundingBox && !boundingBox.containsPoint(camera.position)) {
						let clampedPosition = new THREE.Vector3();
						boundingBox.clampPoint(camera.position, clampedPosition);
						if (clampedPosition) {
							camera.position.copy(clampedPosition);
						}
					}
				});
				// camera.lookAt(that.controlStarPosition.x, that.controlStarPosition.y, that.controlStarPosition.z);
				starRender(); //启动渲染
				renderer.domElement.addEventListener('touchstart', function (event) {
					fingerCount = event.touches.length;//手指个数
					if(fingerCount == 2){
						if(dragControls){
							dragControls.enabled = false;
						}
					}else{
						if(dragControls){
							dragControls.enabled = true;
						}
					}
				});
				
				renderer.domElement.addEventListener('touchmove', function (event) {
					fingerCount = event.touches.length;//手指个数
					if(fingerCount == 2){
						if(dragControls){
							dragControls.enabled = false;
						}
					}else{
						if(dragControls){
							dragControls.enabled = true;
						}
					}
				});
				renderer.domElement.addEventListener('touchend', function (event) {
					fingerCount = 0;//手指个数
					if(dragControls){
						dragControls.enabled = true;
					}
				});
			}
			//把720VR图转化为一个球体模网格型
			function makeShaderCube() {
				let loader = new THREE.TextureLoader();
				let resultTexture = loader.load(that.bgUrl);
				// 创建一个ShaderMaterial
				var material = new THREE.ShaderMaterial({
					uniforms: {
						mytexture: {
							value: resultTexture
						}
					},
					vertexShader: `
						varying vec3 vWorldPosition;
						varying vec2 vUv;    
						void main() {
							vUv = uv;
							vec4 worldPosition = modelMatrix * vec4(position, 1.0);
							vWorldPosition = worldPosition.xyz;
							gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
						}
					`,
					fragmentShader: `
						varying vec2 vUv;
						uniform sampler2D mytexture;
						varying vec3 vWorldPosition;
						
						void main() {
							vec2 uv = vUv;
							vec3 direction = normalize(vWorldPosition);
							vec2 sampleUV = vec2(0.5 + atan(direction.z, direction.x) / (2.0 * 3.14159265359), 0.5 - asin(direction.y) / 3.14159265359);
							vec2 sampleUV1 = vec2(1.0 - uv.x, uv.y);
							gl_FragColor = texture2D(mytexture, sampleUV1);
						}
					`,
					side: THREE.BackSide
				});
				//创建一个球体几何体
				var sphereGeometry = new THREE.SphereGeometry(radius, 60, 40);
				//创建一个球体并应用材质
				var sphere = new THREE.Mesh(sphereGeometry, material);
				scene.add(sphere);
				// 创建一个圆柱几何体
				// var cylinderGeometry = new THREE.CylinderGeometry(50, 50, 100, 60, 1, true);
				// var cylinder = new THREE.Mesh(cylinderGeometry, material);
				// scene.add(cylinder);
			}
			function videoHandle() {
				if(!that.videoUrl){
					return false;
				}
				if(that.repeatFlag){
					return false
				}
				that.repeatFlag = true;
				if(videoMesh){
					that.scene.remove(videoMesh);
					// that.scene.remove(lineMesh);
					dragControls.dispose();
				}
				// 创建一个图片纹理
				const placeholderTexture = new THREE.TextureLoader().load('https://dm.static.elab-plus.com/miniProgram/tab2.jpg');
				const placeholderMaterial = new THREE.MeshBasicMaterial({ map: placeholderTexture });
				let geometry = new THREE.PlaneGeometry(9, 16);
				// 应用绿幕材质到对象上
				let mesh = new THREE.Mesh(geometry, placeholderMaterial);
				// 创建视频元素
				// var video = document.createElement('video');
				var video = document.getElementById('myvideo');
				video.src = that.videoUrl; // 视频文件的路径
				video.setAttribute("crossOrigin", "Anonymous");
				video.loop = true;
				video.muted = that.muted;
				video.controls = false;
				video.autoplay = true;
				video.preload = 'auto';
				video.setAttribute('webkit-playsinline', true);
				video.setAttribute('playsinline', true);
				// video.load();
				setTimeout(() => {
					// video.minFilter = THREE.LinearFilter;
					// video.magFilter = THREE.LinearFilter;
					// video.format = THREE.RGBFormat;
					video.play();
					// console.warn("***video***",video,video.width);
					// 创建视频纹理
					var videoTexture = new THREE.VideoTexture(video);
					// 过滤的颜色值
					var keyColorObject = new THREE.Color("#00ff05");
					var myuniforms = {
					    pointTexture: {
					        type: "t",
					        value: videoTexture
					    },
					    color: {
					        type: "c",
					        value: keyColorObject
					    },
					    videowidth: {
					        type: "f",
					        value: 501.0
					    },
					    videoheight: {
					        type: "f",
					        value: 1024.0
					    },
					    filterType: {
					        type: "i",
					        value: 0
					    },
					    lightLevel: {
					        type: "f",
					        value: 0.2
					    },
					    gridSize: {
					        type: "f",
					        value: 0.8
					    }
					};
					// 创建绿幕着色器
					let greenScreenShader = {
						uniforms: myuniforms,
						transparent: true,
						vertexShader: `    
							varying vec2 vUv;    
							void main() {
								vUv = uv;
								vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
								gl_Position = projectionMatrix * mvPosition;
							}  `,
						fragmentShader: `
							precision mediump float;
							uniform sampler2D pointTexture;
							uniform sampler2D colorlut;
							uniform vec3 color;
							uniform float videowidth;
							uniform float videoheight;
							uniform int filterType;
							uniform float gridSize;
							uniform float lightLevel;
							
							varying vec2 vUv;
							float alter=3.0;
							float u_mode=0.0;
							float u_threshold=1.0;
							float u_clipBlack=0.9;
							float u_clipWhite=1.0;
							
							float rgb2cb(float r, float g, float b){
								return 0.5 + -0.168736*r - 0.331264*g + 0.5*b;
							}
							float rgb2cr(float r, float g, float b){
								return 0.5 + 0.5*r - 0.418688*g - 0.081312*b;
							}
							float smoothclip(float low, float high, float x){
								if (x <= low){
									return 0.0;
								}
								if(x >= high){
									return 1.0;
								}
								return (x-low)/(high-low);
							}
							vec4 greenscreen(vec4 colora, float Cb_key,float Cr_key, float tola,float tolb, float clipBlack, float clipWhite){
								float cb = rgb2cb(colora.r,colora.g,colora.b);
								float cr = rgb2cr(colora.r,colora.g,colora.b);
								float alpha = distance(vec2(cb, cr), vec2(Cb_key, Cr_key));
								alpha = smoothclip(tola, tolb, alpha);
								float r = max(gl_FragColor.r - (1.0-alpha)*color.r, 0.0);
								float g = max(gl_FragColor.g - (1.0-alpha)*color.g, 0.0);
								float b = max(gl_FragColor.b - (1.0-alpha)*color.b, 0.0);
								if(alpha < clipBlack){
									alpha = r = g = b = 0.0;
								}
								if(alpha > clipWhite){
									alpha = 1.0;
								}
								if(clipWhite < 1.0){
									alpha = alpha/max(clipWhite, 0.9);
								}
								return vec4(r,g,b, alpha);
							}
							
							void main()
							{
								gl_FragColor = texture2D( pointTexture, vUv );
								float tola = 0.0;
								float tolb = u_threshold/2.0;
								float cb_key = rgb2cb(color.r, color.g, color.b);
								float cr_key = rgb2cr(color.r, color.g, color.b);
								gl_FragColor = greenscreen(gl_FragColor, cb_key, cr_key, tola, tolb, u_clipBlack, u_clipWhite);
								if(u_mode > 0.5 && u_mode < 1.5){
									gl_FragColor = mix(vec4(1.0, 1.0, 1.0, 1.0), gl_FragColor, gl_FragColor.a);
									gl_FragColor.a = 1.0;
								}
								if(u_mode > 1.5 && u_mode < 2.5){
									gl_FragColor = vec4(gl_FragColor.a, gl_FragColor.a, gl_FragColor.a, 1.0);
								}
								vec4 color = texture2D(pointTexture, vUv);
								if (color.rgb == vec3(0.0, 0.0, 0.0)) {
									discard; 
								}
							}
						`,
					};
					// 创建绿幕材质
					let greenScreenMaterial = new THREE.ShaderMaterial(greenScreenShader);
					greenScreenMaterial.side = THREE.DoubleSide;
					// 应用绿幕材质到对象上
					mesh.material  = greenScreenMaterial;
					mesh.position.copy(lastPosition);//设置视频位置
					// mesh.lookAt(camera.position);
					scene.add(mesh);
					videoMesh = mesh;
					videoMeshChange(that.rangeValue);//同步数字人模型的缩放程度
					// 设置物体的起始位置
					// mesh.userData.startPosition = new THREE.Vector3(0, -10, 0);
					// 创建一个球体几何体
					// var sphereGeometry = new THREE.SphereGeometry(3, 32, 32);
					dragControls = new DragControls([mesh], camera, renderer.domElement );
					dragControls.addEventListener('dragstart', function ( event ) {
						controls.enabled = false;
					});
					// 设置拖拽控制器的监听器
					dragControls.addEventListener('drag', function (event) {
						// 获取mesh的位置
						let position = event.object.position.clone();
						// // 获取包围球的中心点和半径
						let sphereCenter = new THREE.Vector3(0, 0, 0);//原点
						let sphereRadius = radius - 16;
						// 将mesh的位置限制在圆球范围内
						position.sub(sphereCenter).normalize().multiplyScalar(sphereRadius).add(sphereCenter);
						event.object.position.copy(position);
						let distance = position.distanceTo(sphereCenter);
						// console.warn("****position**",position,distance)
						// 	let rad = radius - 16;
						//   // 将拖拽的点转换为球面坐标
						//   var vector = new THREE.Vector3(
						//     (event.object.position.x / rad),
						//     (event.object.position.y / rad),
						//     (event.object.position.z / rad)
						//   ).normalize();
						
						//   // 更新物体的位置
						//   event.object.position.copy(vector.multiplyScalar(10));
						//限制在只能在水平面上移动
						// event.object.position.y = -10;
						//限制不能超过球体
						// let position  = event.object.position;
						// // 获取包围球的中心点和半径
						// let sphereCenter = new THREE.Vector3(0, 0, 0);//原点
						// // 计算mesh和圆球中心点之间的距离
						// let distance = position.distanceTo(sphereCenter);
						// // 判断是否超过包围球的半径-1的距离，是的话则限制
						// if (distance > (radius-1)) {
						// 	const direction = new THREE.Vector3().subVectors(position, sphereCenter).normalize();
						// 	event.object.position.copy(sphereCenter).addScaledVector(direction, (radius-1));
						// }
					});
					dragControls.addEventListener('dragend', function ( event ) {
						controls.enabled = true;
						lastPosition.copy(videoMesh.position);
					});
					// 创建一个PlaneGeometry
					// var planeGeometry = new THREE.PlaneGeometry(9, 16);
					// // 创建一个边框材质
					// var edgeMaterial = new THREE.LineBasicMaterial({ color: 0xffffff});
					// // 创建边框几何体
					// var edges = new THREE.EdgesGeometry(planeGeometry);
					// let line  = new THREE.LineSegments(edges, edgeMaterial);
					// line.position.set(0, -10, -10);//设置视频位置
					// lineMesh = line;
					// scene.add(line);
					that.repeatFlag = false;//释放锁，允许再次点击
				}, 1000)
			}
			function getVideoPosition() {
				if(!videoMesh){
					return '';
				}
				let _position = JSON.stringify(videoMesh.position);
				return _position;
			}
			function getVideoScale() {
				if(!videoMesh){
					return '';
				}
				let scale = JSON.stringify(videoMesh.scale);
				return scale;
			}
			function videoMeshChange(data = 50) {
				if(!videoMesh){
					return false
				}
				let sca = (data - 50)/50 + 1;
				if(sca >= 1){
					sca = sca *2;
				}
				videoMesh.scale.x = sca
				videoMesh.scale.y = sca
			}
			function stopRender() {
				needRender = false;
			}

			function starRender() {
				if (needRender == true) { //如果已经在渲染中了，则不能再次开启，避免渲染过多
					false;
				}
				needRender = true;
				render(); //开始渲染
			}
			
			function render() {
				if (needRender == false) {
					return false;
				}
				// stats.update();
				controls.update();
				if(videoMesh){
					videoMesh.lookAt(camera.position);
					// lineMesh.lookAt(camera.position);
					// lineMesh.position.copy(videoMesh.position)
				}
				renderer.render(scene, camera); //单次渲染
				requestId = requestAnimationFrame(render, canvas3d);
			}

		},
		methods: {
			rangeChange(e){
				this.videoMeshChange(this.rangeValue)
			},
			navbarBackClk() {

			},
			clearHandle() {
				this.clearEvent();
			},
			updateMuted(){
				this.muted = !this.muted;
			},
			iosPlay(){
				this.videoHandle();
				this.hasOneTouch = true;
			},
			aiPeopleChange(item){
				let self = this;
				console.warn("***aiPeopleChange***",item);
				if(!item || !item.url){
					Toast({
						message: '没有地址...请稍后再试',
					});
					return false;
				}
				self.videoUrl = item.url;
				if(self.hasOneTouch==false){
					if(self.isIOS){
						// document.addEventListener("WeixinJSBridgeReady", self.iosPlay, false)
						wx.config({
							debug: false,
							appId: '',
							timestamp: '',
							nonceStr: '',
							signature: '',
							jsApiList: []
						})
						wx.ready(function() {
							// 在这里面进行操作即可，估计应该是微信的sdk对Safari的内核做了一些对应的操作吧
							self.iosPlay()
						})
					}else{
						// var guideMask = document.querySelector('#guide-mask');
						document.addEventListener("touchend", ()=> {
							// guideMask.classList.add('guide-mask-hide');
							if(self.hasOneTouch==false){
								self.hasOneTouch = true;
								self.videoHandle();
							}
						}, false);
					}
					
				}else{
					self.videoHandle();
				}
			}
		}
	}
</script>
<style lang="scss" scoped>
	@import "./webgl_rxdz_vr.scss";
	/* @import "@/common/css/common.css"; */
</style>