Procházet zdrojové kódy

测试绿幕视频

zjs_project před 1 rokem
rodič
revize
22b067ddb2

+ 29 - 0
src/pages/webgl_rxdz_vr/webgl_rxdz_vr.html

@@ -0,0 +1,29 @@
+<!--
+ * @Author: caodongdong caodongdoong@gmail.com
+ * @Date: 2023-05-17 15:46:34
+ * @LastEditors: caodongdong caodongdoong@gmail.com
+ * @LastEditTime: 2023-06-30 16:20:04
+ * @FilePath: \h5-uniApp-miniprogrgm\webgl\pages\webgl_rxdz\webgl_rxdz.html
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+-->
+<div class="main-view">
+	<mynavbar :barData='navbar' @navbarBackCallback="navbarBackClk" />
+	<!-- 主要操作视图 -->
+	<!-- <viewShell pageType="2" :spaceObj="curSpaceObj" @hideOrShowActor="hideOrShowActor"></viewShell> -->
+	<!-- <my-loading ref="myLoading" :myLoadingStatus="myLoadingStatus"></my-loading>
+	<div id="status" style="position:fixed;top:100px;left:30px;cursor:pointer;opacity:0.9;z-index:10000">
+		<canvas id="FPS" type="2d" style="width:80px;height:48px"></canvas>
+		<canvas id="MS" type="2d" style="width:80px;height:48px"></canvas>
+	</div> -->
+	<div id="mapDiv" ref="webgl"></div>
+	<canvas id="canvas_webgl" type="webgl" ref="glcanvas"
+		 width="100vw" 
+		:style="{'height':canvasHeight+'px'}">
+	</canvas>
+	<!-- AI结果覆盖层 -->
+	<!-- <viewMask ref="viewMask" @switchActor="switchActor" style="z-index: 13;"
+	  :spaceObj="curSpaceObj" ></viewMask> -->
+	<!-- 生成截屏的画布对象 -->
+	<canvas id="canvas" type="2d" :style="{'height':canvasHeight+'px','top':'100vh'}"></canvas>
+	<!-- <video id="video" style="display:none" autoplay playsinline src="https://dm.static.elab-plus.com/miniProgram/green.mp4"></video> -->
+</div>

+ 31 - 0
src/pages/webgl_rxdz_vr/webgl_rxdz_vr.scss

@@ -0,0 +1,31 @@
+.main-view{
+	width:100vw;
+	height:100vh;
+	overflow: hidden;
+}
+canvas { width:100vw; height:calc(100vh - 408px);z-index: 10;}
+#mapDiv{
+	background-color: #fff;
+}
+page {
+    -webkit-user-select: none;
+    user-select: none;
+    width: 100%;
+	height:100vh;
+    overflow-x: hidden;
+    overflow-y: hidden;
+}
+/* 生成截屏的画布对象 */
+#canvas {
+	width: 100vw;
+	z-index: -1;
+	// position: absolute;
+	left:0px;
+}
+.canvas-view{
+	position:relative;
+}
+.lable-view{
+	position:absolute;
+	width:100vw;
+}

+ 692 - 0
src/pages/webgl_rxdz_vr/webgl_rxdz_vr.vue

@@ -0,0 +1,692 @@
+<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 {
+		GLTFLoader
+	} from 'three/addons/loaders/GLTFLoader.js';
+
+	import TWEEN from 'three/addons/libs/tween.module.js';
+	import {
+		getStorage
+	} from '@/utils/localStorage';
+	var requestId = "";
+	const util = require('@/utils/util.js').default;
+	// import util from '@/utils/util.js';
+	// const config = require('@/services/urlConfig.js');
+	// import requestConfig from '@/static/lib/requestConfig.js';
+	import viewShell from '@/components/newBottomCom/viewShell/viewShell.vue';
+	import viewMask from '@/components/newBottomCom/viewMask/viewMask.vue';
+
+	// import { RGBELoader } from '@/webgl/jsm/loaders/RGBELoader.js';
+	import screenshot from '@/mixins/screenshot.js';
+	import floorMethod from '@/mixins/floorMethod.js';
+	import loadModel from '@/mixins/loadModel.js';
+	import wallMethod from '@/mixins/wallMethod.js';
+	import commonPageMethod from '@/mixins/commonPageMethod.js';
+	// import commonPageMethod from '@/common/commonPageMethod.js';
+	// const app = getApp(); //获取应用实例
+	export default {
+		components: {
+			viewShell,
+			viewMask
+		},
+		mixins: [screenshot, loadModel, floorMethod, wallMethod, commonPageMethod],
+		/**
+		 * 页面的初始数据
+		 */
+		data() {
+			return {
+				pvCurPageName: "room_show",
+				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: '', // 户型编号
+				spaceList: [], // 空间列表
+				gltfSpaces: [], // 场景中地板模型数组
+				gltfSpaceRoofs: [],
+				curSpaceObj: null, // 当前选中的空间
+				// curSpaceIndex:-1, // 当前选中的空间索引
+				spaceId: null,
+				wallIds: [], // 空间墙体id
+				// wallList:[], // 墙体数据
+				gltfWalls: [], // 场景中墙体模型数组
+				loader: null,
+				scene: null,
+				// sky:null,
+				camera: null,
+				controlStarPosition: {
+					x: 0,
+					y: 0,
+					z: 0
+				}, //控制器初始位置
+				cameraStarPosition: {
+					x: 0,
+					y: 20,
+					z: 0
+				}, //摄像头初始位置
+				cameraLastPosition: null, //摄像头上一次移动到的位置
+				controlLastPosition: null, //观察点上一次移动到的位置
+				canvasHeight: 408, //canvas视图的高度-计算得出
+				chooseMesh: null, //标记鼠标拾取到的mesh
+				shottingImg: [],
+				progress: 1, //进度条
+				myLoadingStatus: false,
+				// textGeoList:[],
+				repeatFlag: false, //重复点击
+				// skyPlan: null, // 天空盒子
+				instancedMeshList: [],
+				screenshotResolve: null,
+				actors: [],
+				showDownView: true, //默认显示下载按钮
+				currentActor: null,
+				circleGroup: null, //圆形地标
+				isIOS: false,
+				defaulIndex: null, //默认视角的序号
+				// aiImagesList:[
+				// 	// "https://dm.static.elab-plus.com/miniProgram/plus_IM01.png",
+				// 	// "https://dm.static.elab-plus.com/miniProgram/plus_IM02.png",
+				// 	// "https://dm.static.elab-plus.com/miniProgram/plus_IM03.png",
+				// 	// "https://dm.static.elab-plus.com/miniProgram/plus_IM04.png",
+				// ]
+			}
+		},
+		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;;
+				this.clearHandle()
+			}
+			TWEEN && TWEEN.removeAll(); //清除所有的tween;
+			console.warn("***beforeDestroy-webgl_rxdz_roam***");
+		},
+		mounted(options) {
+			var that = this;
+			// alert("JavaScript 堆大小限制: "+performance.memory.jsHeapSizeLimit
+			// +"\n已使用的 JavaScript 堆大小: "+performance.memory.usedJSHeapSize
+			// +"\nJavaScript 堆的总大小: "+performance.memory.totalJSHeapSize);
+			console.warn("***webgl_rxdz_roam-options***", this.$route.query)
+			this.isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
+
+			// 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.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 loader = this.loader = new GLTFLoader();
+			let scene = this.scene = new THREE.Scene();
+			let raycaster = null;
+			let mouse = new THREE.Vector2();
+			let chooseMesh = this.chooseMesh; //标记鼠标拾取到的mesh
+			let isUserContorl = true; //是否进入漫游状态-默认是
+			//漫游时变量
+			let onPointerDownMouseX = 0,
+				onPointerDownMouseY = 0,
+				lon = 0;
+			let fingerCount = 0; //触摸时的手指数目
+			let startTime = 0; //非漫游时的移动变量
+			let tweenCameraAnma = false; //表示当前是否处在动画过程中
+			let controls = null,
+				boundary = null;
+			let stats;
+			init();
+			// this.$refs.myLoading.showLoading("加载中...1%")
+			// this.myLoadingStatus = true;
+			this.clearEvent = clearEvent;
+			this.attendEvent = attendEvent;
+			this.tweenCameraAnmaChange = tweenCameraAnmaChange;
+			this.starRender = starRender; //对外暴露启动渲染的方法
+			this.stopRender = stopRender; //对外暴露停止渲染的方法
+
+			function init() {
+
+				// scene.background = new THREE.Color("#FFFFFF");
+				// scene.environment = new THREE.Color("#F2F2F2");
+				// 创建一个HDR贴图加载器
+				// const rgbeloader = new RGBELoader();
+				// // 加载HDR贴图
+				// rgbeloader.load('https://dm.static.elab-plus.com/miniProgram/environment.hdr', (texture) => {
+				// 	// 将HDR贴图设置为场景的环境贴图
+				// 	texture.mapping = THREE.EquirectangularReflectionMapping;
+				// 	scene.environment = texture;
+				// })
+
+				// 创建相机位置
+				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;
+
+				// 环境光会均匀的照亮场景中的所有物体
+				const ambientLight = new THREE.AmbientLight(0xFFEFE0, 3.5);
+				scene.add(ambientLight);
+
+				const loader = new THREE.TextureLoader();
+				const texture = loader.load(
+					'https://dm.static.elab-plus.com/miniProgram/tears_of_steel_bridge_2k.jpg', () => {
+						const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);
+						rt.fromEquirectangularTexture(renderer, texture);
+						scene.background = rt.texture;
+					});
+				//antialias 这个值得设置为false,不然IOS上截图会失效
+				renderer = that.renderer = new THREE.WebGLRenderer({
+					canvas: canvas3d,
+					alpha: true,
+					antialias: true,
+					preserveDrawingBuffer: true,
+				});
+				if (!that.isIOS) {
+					renderer.shadowMap.enabled = true; //产生阴影
+					renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 阴影属性
+				}
+				renderer.outputEncoding = THREE.sRGBEncoding;
+				renderer.outputColorSpace = THREE.SRGBColorSpace;
+				// renderer.toneMappingExposure = 0.1;//色调映射的曝光级别。默认是1
+				renderer.toneMapping = THREE.NoToneMapping; //色调映射
+				renderer.physicallyCorrectLights = true; //关键参数,模拟物理光照影响,必须设置为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 = 10;
+				controls.minPolarAngle = 0; // 默认0
+				controls.maxPolarAngle = Math.PI / 2; // 默认Math.PI,即可以向下旋转到的视角。
+				// controls.target.set(  that.controlStarPosition.x, that.controlStarPosition.y, that.controlStarPosition.z);
+				controls.enableZoom = true; //启用摄像机的缩放
+				controls.enablePan = true; //禁用摄像机平移
+				controls.enableRotate = true; //启用摄像机水平或垂直旋转
+				// controls.zoomToCursor = true;
+
+				// controls.target.copy(camera.position);
+				// controls.update();
+				// 监听相机移动事件-限制只能在当前空间范围内移动
+				controls.addEventListener('change', () => {
+					// 检查相机位置是否超出边界框
+					if (boundary && !boundary.containsPoint(camera.position)) {
+						let clampedPosition = new THREE.Vector3();
+						boundary.clampPoint(camera.position, clampedPosition);
+						if (clampedPosition) {
+							camera.position.copy(clampedPosition);
+							// controls.target.copy(clampedPosition);
+						}
+					}
+				});
+				// controls.target = new THREE.Vector3( );;
+				camera.lookAt(that.controlStarPosition.x, that.controlStarPosition.y, that.controlStarPosition.z);
+				raycaster = new THREE.Raycaster();
+				// stats = new Stats();
+				// container.appendChild(stats.dom);
+				// stats.domElement.style.top = '100px';
+				attendEvent(); //注册监听事件
+				starRender(); //启动渲染
+				setTimeout(() => {
+					videoHandle()
+				}, 500);
+			}
+
+			function videoHandle() {
+				// let video = document.getElementById('video');
+
+				// let texture = new THREE.VideoTexture(video);
+				// texture.colorSpace = THREE.SRGBColorSpace;
+
+				// 创建视频元素
+				var video = document.createElement('video');
+				video.src = 'https://dm.static.elab-plus.com/miniProgram/green.mp4'; // 视频文件的路径
+				// video.crossOrigin = "anonymous";this.crossOrigin = 'anonymous';
+				video.setAttribute("crossOrigin", "Anonymous");
+				video.loop = true;
+				video.muted = true;
+				// video.load();
+				video.play();
+				// 创建视频纹理
+				var texture = new THREE.VideoTexture(video);
+				// texture.colorSpace = THREE.SRGBColorSpace;
+				// texture.minFilter = THREE.LinearFilter;
+				// texture.magFilter = THREE.LinearFilter;
+				// texture.format = THREE.RGBFormat;
+
+				// 创建绿幕着色器
+				let greenScreenShader = {
+					uniforms: {
+						pointTexture: {
+							value: texture
+						},
+					},
+					vertexShader: `    
+						varying vec2 vUv;    
+						void main() {      
+							vUv = uv;      
+							gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);    
+						}  `,
+					fragmentShader: `
+						uniform sampler2D pointTexture;
+						varying vec2 vUv;
+						void main() {
+						    vec4 color = texture2D(pointTexture, vUv);
+						    float threshold = 0.5;
+						    if (color.g > threshold) {
+								discard; 
+						    } else {
+								gl_FragColor = color;
+						    }
+						}
+					`,
+
+					// 		fragmentShader: `    
+					// 			uniform sampler2D pointTexture;
+					// 			uniform vec3 backColor;
+					// 			varying vec2 vUv;
+					// 			uniform float u_threshold;
+					// 			float u_clipBlack = 0.2;
+					// 			float u_clipWhite = 4.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)*backColor.r, 0.0); 
+					// 				float g = max(gl_FragColor.g - (1.0-alpha)*backColor.g, 0.0); 
+					// 				float b = max(gl_FragColor.b - (1.0-alpha)*backColor.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( void ) {
+
+					// 				gl_FragColor = vec4(texture2D(pointTexture, vUv).rgb, 1);
+
+					// 				float tola = 0.0; 
+					// 				float tolb = u_threshold/2.0; 
+					// 				float cb_key = rgb2cb(backColor.r, backColor.g, backColor.b); 
+					// 				float cr_key = rgb2cr(backColor.r, backColor.g, backColor.b); 
+					// 				gl_FragColor = greenscreen(gl_FragColor, cb_key, cr_key, tola, tolb, u_clipBlack, u_clipWhite);
+
+					// 			} 
+					// 			`,
+
+				};
+				// 创建绿幕材质
+				let greenScreenMaterial = new THREE.ShaderMaterial(greenScreenShader);
+
+				let geometry = new THREE.PlaneGeometry(16, 9);
+				// var geometry = new THREE.BoxGeometry(9, 9, 9);
+				// geometry.scale(0.5, 0.5, 0.5);
+				// 应用绿幕材质到对象上
+				let mesh = new THREE.Mesh(geometry, greenScreenMaterial);
+				mesh.position.set(0, 0, 0);
+				// mesh.rotation.x =  -Math.PI / 2 ;  // 旋转 180 度
+				// scene.add(object);
+				// const mesh = new THREE.Mesh(geometry, material);
+				// mesh.position.setFromSphericalCoords(radius, phi, theta);
+				mesh.lookAt(camera.position);
+				scene.add(mesh);
+			}
+
+			function tweenCameraAnmaChange(value) {
+				tweenCameraAnma = value
+			}
+
+			function attendEvent() {
+				renderer.domElement.addEventListener('touchstart', onPointerStart, false);
+				renderer.domElement.addEventListener('touchmove', onPointerMove, false);
+				renderer.domElement.addEventListener('touchend', onPointerUp, false);
+			}
+			//取消事件监听-避免二次进入时触发多次事件
+			function clearEvent() {
+				console.warn("**clearEvent****")
+				renderer && renderer.domElement && renderer.domElement.removeEventListener('touchstart', onPointerStart);
+				renderer && renderer.domElement && renderer.domElement.removeEventListener('touchmove', onPointerMove);
+				renderer && renderer.domElement && renderer.domElement.removeEventListener('touchend', onPointerUp);
+			}
+			// 手指移动开始
+			function onPointerStart(event) {
+				startTime = (new Date()).getTime();
+				fingerCount = event.touches.length; //手指个数
+				console.log('开始触摸事件:', lon, fingerCount, camera.position.y)
+				if (fingerCount === 1) {
+					// 只有一个手指时记录当前点的坐标作为平移起始点
+					onPointerDownMouseX = event.changedTouches[0].clientX;
+					onPointerDownMouseY = event.changedTouches[0].clientY;
+				}
+
+			}
+			//持续触摸中
+			function onPointerMove(event) {
+				fingerCount = event.touches.length; //手指个数
+			}
+			//触摸结束
+			function onPointerUp(event) {
+				fingerCount = event.touches.length; //手指个数
+				console.warn("***触摸结束***", fingerCount, startTime)
+				if (fingerCount == 0) {
+					let now = new Date().getTime()
+					if (Math.abs(event.changedTouches[0].clientX - onPointerDownMouseX) < 10 &&
+						Math.abs(event.changedTouches[0].clientY - onPointerDownMouseY) < 10 &&
+						(now - startTime) < 300) {
+						checkIntersection(event);
+					}
+				}
+			}
+			//射线检测handle
+			function checkIntersection(event) {
+				let x = (event.changedTouches[0].clientX / screenWidth) * 2 - 1;
+				let y = -(event.changedTouches[0].clientY / that.canvasHeight) * 2 + 1;
+				mouse.x = x;
+				mouse.y = y;
+				//更新射线
+				raycaster.setFromCamera(mouse, camera);
+				let intersects = raycaster.intersectObjects(scene.children, true);
+				console.warn("***checkIntersection***", intersects.length)
+				if (intersects.length > 0) {
+					//找到最近的那个网格模型物体
+					let mesh = intersects.find((it) => {
+						if (it.object && it.object.isMesh == true &&
+							it.object.parent && it.object.parent.name == 'actor' &&
+							it.object.parent.visible == true) {
+							return true;
+						}
+					});
+
+					//拾取到了视角,就不继续拾取了
+					if (mesh) {
+						moveActor(mesh.object.parent);
+						return false;
+					}
+					mesh = intersects.find((it) => {
+						if (it.object && it.object.isInstancedMesh &&
+							(it.object.name == '地板' || it.object.name == '花园') && it.object.visible == true) {
+							return true;
+						}
+					});
+					//拾取到了地板
+					if (mesh) {
+						let floor = mesh.object;
+						let index = mesh.instanceId; //射线相交是的实例序号
+						let spaceId = that.gltfSpaces[index].spaceId; //获取选中实例的空间id
+						if (floor.name == "花园") { //花园
+							return false;
+							let selectMesh = that.gltfSpaces.find(it => {
+								return it.spaceType == 14 && it.instancedMeshIndexList[0].instancedAtIndex == index
+							})
+							spaceId = selectMesh.spaceId;
+						} else { //室内
+							// floor.name = "地板";
+							let selectMesh = that.gltfSpaces.find(it => {
+								return it.spaceType != 14 && it.instancedMeshIndexList[0].instancedAtIndex == index
+							})
+							spaceId = selectMesh.spaceId;
+						}
+						// let spaceId = that.gltfSpaces[index].spaceId;//获取选中实例的空间id
+						console.warn("***checkIntersection-地板***", floor, index, spaceId, that.spaceId)
+						//当前拾取到的是本空间的底部-意味着用户点击了地板
+						if (floor && spaceId == that.spaceId) {
+							moveCarmer(mesh.point);
+							return false;
+						}
+					}
+				}
+			}
+
+			function tweenCamera(oldP, oldT, newP, newT, oldUp, newUp, time = 1000) {
+				if (JSON.stringify(oldP) == JSON.stringify(newP) && JSON.stringify(oldT) == JSON.stringify(newT)) {
+					that.repeatFlag = false; //放开限制,可以再次点击
+					return false;
+				}
+				if (!chooseMesh) {
+					that.repeatFlag = false; //放开限制,可以再次点击
+					return false;
+				}
+				tweenCameraAnma = true;
+				var tween = new TWEEN.Tween({
+						x1: oldP.x, // 相机x
+						y1: oldP.y, // 相机y
+						z1: oldP.z, // 相机z
+						x2: oldT.x, // 控制点的中心点x
+						y2: oldT.y, // 控制点的中心点y
+						z2: oldT.z, // 控制点的中心点z
+						x3: oldUp.x, // 控制点的中心点x
+						y3: oldUp.y, // 控制点的中心点y
+						z3: oldUp.z // 控制点的中心点z
+					})
+					.to({
+						x1: newP.x,
+						y1: newP.y,
+						z1: newP.z,
+						x2: newT.x,
+						y2: newT.y,
+						z2: newT.z,
+						x3: newUp.x, // up向量
+						y3: newUp.y, // 控制点的中心点y
+						z3: newUp.z // 控制点的中心点z
+					}, time)
+					.easing(TWEEN.Easing.Quadratic.InOut)
+					.onUpdate((object) => {
+						camera.position.x = object.x1;
+						camera.position.y = object.y1;
+						camera.position.z = object.z1;
+						// let newTarget = new THREE.Vector3(object.x3,object.y3,object.z3);
+						// camera.up.copy(newTarget);
+						camera.lookAt(object.x2, object.y2, object.z2);
+						// controls.target.x = object.x2;
+						// controls.target.y = object.y2;
+						// controls.target.z = object.z2;
+						// controls.update();
+					}).onComplete(() => {
+						controls.target.x = newT.x;
+						controls.target.y = newT.y;
+						controls.target.z = newT.z;
+						//修正最后的视角
+						// let up = new THREE.Vector3(newUp.x,newUp.y,newUp.z);
+						// camera.up.copy(up);
+						camera.lookAt(newT.x, newT.y, newT.z);
+						tweenCameraAnma = false;
+						that.repeatFlag = false; //放开限制,可以再次点击
+					})
+				// 开始动画
+				tween.start();
+			}
+
+			function stopRender() {
+				needRender = false;
+			}
+
+			function starRender() {
+				if (needRender == true) { //如果已经在渲染中了,则不能再次开启,避免渲染过多
+					false;
+				}
+				needRender = true;
+				render(); //开始渲染
+			}
+
+			function render() {
+				if (needRender == false) {
+					return false;
+				}
+				TWEEN && TWEEN.update();
+				// stats.update();
+				renderer.render(scene, camera); //单次渲染
+				requestId = requestAnimationFrame(render, canvas3d);
+				if (that.screenshotResolve) {
+					stopRender();
+					that.screenshotResolve()
+					that.screenshotResolve = null; //释放Promise
+				}
+			}
+
+		},
+		// computed: {
+		// 	curHouseObj() {
+		// 		return this.$store.state.curHouseObj;
+		// 	},
+		// 	wallList() {
+		// 		return this.$store.state.wallList;
+		// 	},
+		// },
+		methods: {
+			navbarBackClk() {
+
+			},
+			clearHandle() {
+				this.clearEvent();
+			},
+			save() {
+				this.$refs.viewMask.save(); //下载
+			},
+			/**
+			 * 设置户型详情信息
+			 * @param {Object} data 户型详情
+			 */
+			setHouseDetail(data) {
+				if (data) {
+					this.id = data.id;
+					this.spaceId = this.$route.query.spaceId ? this.$route.query.spaceId : '';
+					console.warn("***curHouseObj***", data)
+					// 加载户型
+					this.loadSpace();
+				} else {
+					this.curHouseObj = {}
+				}
+			},
+			// 绘制空间-即地板
+			async loadSpace() {
+				this.spaceList = [];
+				this.wallIds = [];
+				if (!this.curHouseObj || !this.spaceId) { //减少重复请求
+					alert("数据错误")
+					console.warn("***数据错误***")
+					return false
+				}
+				if (this.curHouseObj) {
+					const spaceDetail = this.curHouseObj;
+					const spaceList = JSON.parse(spaceDetail.houseJson);
+					// 交换centerX, centerY;上一页面已经处理过了,这里不在需要处理
+					for (let index = 0; index < spaceList.length; index++) {
+						var element = spaceList[index];
+						// const centerX = JSON.parse(JSON.stringify(element.centerX))
+						if (!element.actors || element.actors.length == 0) {
+							element.actors = [{
+								actorLocation: element.actorLocation,
+								actorTransform: element.actorTransform,
+								isSelected: true,
+							}]
+						}
+						element.actors.forEach(actor => {
+							let _actorLoaction = actor.actorLocation.split(','); //x y z
+							let X_C = parseInt(_actorLoaction[0]); //X轴偏移量-UE原因
+							let Y_C = -parseInt(_actorLoaction[1]); //Y轴偏移量-取反,UE里面的Y轴方向跟Three.js相反
+							let _x = element.centerX + X_C;
+							let _z = -element.centerY + Y_C; //centerY 要取反,因为UE里面是反向的
+
+							// let _x = parseInt(_actorLoaction[1]) || element.centerX;//观察点 X轴坐标 
+							// let _z = parseInt(_actorLoaction[0]) || element.centerY;//观察点 Z轴坐标
+							let _presentX = (_x - element.centerX) / ((element.spaceWidth / 2) -
+								10); //10是墙壁厚度-单位cm
+							let _presentY = (_z + element.centerY) / ((element.spaceHeight / 2) - 10);
+							//注意如果一开始就设置大超过空间大小,则处理成贴近空间边界
+							actor.presentX = Math.abs(_presentX) > 1 ? (_presentX > 1 ? 1 : -1) :
+								_presentX; //观察点跟空间中心原点的距离比例
+							actor.presentY = Math.abs(_presentY) > 1 ? (_presentY > 1 ? 1 : -1) : _presentY;
+						})
+						element.wallMoveValue = "[0,0,0,0]"
+						this.spaceList.push(element);
+						this.wallIds.push(element.wallId);
+
+						if (element.spaceId == this.spaceId) { // 默认选中空间
+							this.curSpaceObj = element;
+						}
+					}
+					if (!this.curSpaceObj && this.spaceList.length > 0) {
+						this.curSpaceObj = this.spaceList[0];
+					}
+				}
+				let curSpaceArea = parseFloat((this.curSpaceObj.spaceWidth * this.curSpaceObj.spaceHeight) / 10000)
+					.toFixed(1);
+				this.navbar.title = this.curSpaceObj.spaceName + "  " + curSpaceArea + "㎡"
+				console.log("该户型空间数据:", this.spaceList);
+				console.log("当前选中的空间:", this.curSpaceObj);
+				// 获取墙体数据并且绘制墙体
+			},
+
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	@import "./webgl_rxdz_vr.scss";
+	/* @import "@/common/css/common.css"; */
+</style>

+ 10 - 0
src/router/index.js

@@ -9,6 +9,8 @@ import webgl_rxdz_roam from '@/pages/webgl_rxdz_roam/webgl_rxdz_roam.vue'
 import webgl_rxdz_look from '@/pages/webgl_rxdz_look/webgl_rxdz_look.vue'
 import webgl_rxdz_customize from '@/pages/webgl_rxdz_customize/webgl_rxdz_customize'
 
+import webgl_rxdz_vr from '@/pages/webgl_rxdz_vr/webgl_rxdz_vr.vue'
+
 Vue.use(Router)
 const router = new Router({
     mode: 'hash',
@@ -58,6 +60,14 @@ const router = new Router({
 			meta:{
 				keepAlive:false
 			}
+		},
+		{
+		    path: '/pages/webgl_rxdz_vr',
+		    name: 'webgl_rxdz_vr',
+		    component: webgl_rxdz_vr,
+			meta:{
+				keepAlive:false
+			}
 		}
 		
     ],