Parcourir la source

同步小程序的webgl

zjs_project il y a 1 an
Parent
commit
c880174de1

+ 41 - 0
src/components/mapComponent - 副本/mapComponent.css

@@ -0,0 +1,41 @@
+#mapDiv{
+    width: 100%;
+    height: 100vh;
+    background: #181C28;
+}
+.map {
+  position: relative;  /* 作为子元素的相对定位元素 */
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+}
+#labels {
+  position: absolute;  /* 把Label定位在容器内 */
+  left: 0;             /* 默认定位在左上角 */
+  top: 0;
+  color: white;
+}
+#labels>div {
+  position: absolute;  /* 让我们的容器决定尺寸 */
+  left: 0;             /* 默认定位在左上角 */
+  top: 0;
+  cursor: pointer;     /* 当悬浮时,变为一个小手 */
+  font-size:12px;
+  user-select: none;   /* 不允许文字被选中 */
+  white-space: nowrap;
+  text-shadow:         
+    -1px -1px 0 #000,
+    0   -1px 0 #000,
+    1px -1px 0 #000,
+    1px  0   0 #000,
+    1px  1px 0 #000,
+    0    1px 0 #000,
+    -1px  1px 0 #000,
+    -1px  0   0 #000;
+}
+#labels>div:hover {
+  color: red;
+}
+canvas:focus {
+  outline:none;
+}

+ 9 - 0
src/components/mapComponent - 副本/mapComponent.html

@@ -0,0 +1,9 @@
+<div class="map" style="position: absolute;width: 100%;height: 100vh;z-index: 1;">
+    <div id="mapDiv" ref="webgl"></div>
+	<canvas id="glcanvas" width="100vw" height="100vh" ref="glcanvas">
+		你的浏览器似乎不支持或者禁用了 HTML5 <code>&lt;canvas&gt;</code> 元素。
+	</canvas>
+	<div id="labels"></div>
+	<!-- 左侧操作区域 -->
+	<left-operate-comp @operateHandle="operateHandle"></left-operate-comp>
+</div>

+ 691 - 0
src/components/mapComponent - 副本/mapComponent.vue

@@ -0,0 +1,691 @@
+<template src="./mapComponent.html"></template>
+<script>
+	// import AMapLoader from "@amap/amap-jsapi-loader";
+	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 { DragControls } from 'three/addons/controls/DragControls.js';
+	import leftOperateComp from "@/components/leftOperateComp/leftOperateComp";
+	export default {
+		name: "mapComponent",
+		props: {},
+		components:{
+			leftOperateComp
+		},
+		data() {
+			return {
+				area: null,
+				selectModuleItem: null,
+				showMap: false,
+				is3D: true,
+				isOpen: false, //是否打开项目展示
+				scene: null,
+				camera: null,
+				canvas: null,
+				renderer: null,
+				stats:null,
+				starWorldPosition:null,
+				drawAreaObject:null,
+				XLine:null,
+				YLine:null,
+				areaList:[],//用户绘制的空间存放的数据对象
+				pageStatus:1,	//当前页面状态 1 显示态 2 编辑态
+				cursorObj:null,	//鼠标当前划过的对象
+				cursorMeshColor:null,	//记录下划过对象的元素颜色
+				moveObj:null,	//移动对象
+				moveStarPosition:null,	//移动对象的初始位置-用于计算移动距离
+				adsorbDis:0.3,			//移动对象时的吸附距离
+			};
+		},
+		created() {},
+		watch: {
+			// areaData: {
+			// 	handler(newVal) {
+			// 		if(newVal){
+			// 			this.loadMap();
+			// 		}
+			// 	},
+			// 	immediate: true
+			// }
+		},
+		mounted() {
+			var isDrawing = false;
+			// this.loadMap();
+			// window.$bus.$off('loginSuccess',this.loadMap);
+			// window.$bus.$on('loginSuccess', this.loadMap);
+			// window.$bus.$off('resetMap');
+			// window.$bus.$on('resetMap', (data) => {
+			// 	this.isOpen = data;
+			// 	this.resetMapCenter();
+			// })
+			var that = this;
+			const container = this.$refs.webgl;
+			this.stats = new Stats();
+			container.appendChild(this.stats.dom);
+			
+			this.scene = new THREE.Scene();//场景对象
+			this.scene.background = new THREE.Color("#fff");//设置场景的背景色
+			// this.scene.environment = new THREE.Color("#ccc");
+			//创建透视相机
+			this.camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 0.1, 10000);
+			this.camera.position.set(0, 0, 15);
+			this.scene.add(this.camera);//把相机添加到场景里面
+			// const ambientLight = new THREE.AmbientLight(0xffffff, 0.3);
+			// this.scene.add( ambientLight );
+			const canvas3d = this.$refs.glcanvas;
+			//创建渲染器
+			this.renderer = new THREE.WebGLRenderer({
+				canvas:canvas3d,
+				antialias: false,
+				preserveDrawingBuffer: true,
+			});
+			this.renderer.setPixelRatio(window.devicePixelRatio);
+			this.renderer.setSize(window.innerWidth, window.innerHeight);
+			container.appendChild(this.renderer.domElement);
+
+			//极坐标辅助
+			// const axesHelper = new THREE.AxesHelper( 50 );
+			// this.scene.add( axesHelper );
+			//网格辅助
+			const gridHelper = new THREE.GridHelper(50, 50, 0x808080, 0x808080);
+			gridHelper.position.y = 0;
+			gridHelper.position.x = 0;
+			gridHelper.rotation.x = Math.PI / 2;//翻转
+			gridHelper.name = "辅助网格"
+			this.scene.add(gridHelper);
+			
+			// 4.创建一个长、宽、高均为5个单位的立方体
+			// const geometry = new THREE.BoxGeometry(5, 5, 5);
+			// 创建一个长、宽、的矩形;three.js 默认单位是米
+			const geometry = new THREE.PlaneGeometry(50, 50);
+
+			// 5.创建Lambert网格材质
+			const materialBasic = new THREE.MeshBasicMaterial({
+				color: 'transparent', // 绿色
+				transparent: true, // 设置材质为透明
+				opacity: 0.5 // 设置透明度
+			});
+			// 6.创建一个网格模型对象
+			const mesh = new THREE.Mesh(geometry, materialBasic); //网络模型对象Mesh
+			mesh.position.set(0, 0, 0);
+			mesh.name="bgPan";//背景板-用于计算鼠标点击以及滑动时的位置-精确位置
+			// 把网格模型添加到三维场景
+			this.scene.add(mesh);
+			
+			// 设置相机看向物体的方向(默认指向三维坐标系的原点)
+			// this.camera.lookAt(0, 0, 0);
+			// 修改几何体位置
+			// const controls = new OrbitControls( this.camera, this.renderer.domElement );
+			// controls.target.set( 0, 0.5, 0 );
+			// controls.update();
+			// controls.enablePan = false;
+			// controls.enableDamping = true;
+			
+			// function render(){
+			// 	this.renderer.render(this.scene, this.camera);//单次渲染
+			// 	requestAnimationFrame(render)
+			// }
+			const raycaster = new THREE.Raycaster();
+			this.render(); //开启渲染
+			this.renderer.domElement.addEventListener('pointermove', onMouseMove, false);
+			this.renderer.domElement.addEventListener('pointerup', mouseup, false);//释放鼠标
+			this.renderer.domElement.addEventListener('pointerdown', mousedown, false);//按下鼠标
+			document.addEventListener('contentmenu', contentmenu, false);//右键事件
+			const labelContainerElem = document.querySelector('#labels');//获取页面上的标签层元素
+			window.onresize = ()=> {
+				this.camera.aspect = window.innerWidth / window.innerHeight;
+				this.camera.updateProjectionMatrix();
+				this.renderer.setSize( window.innerWidth, window.innerHeight );
+			};
+			//把鼠标的点击坐标-屏幕坐标转换为three.js体系里面的世界坐标
+			function getWorldPoint (event) {
+				var mouse = new THREE.Vector2();
+				mouse.x = (event.clientX / window.innerWidth) * (2/window.devicePixelRatio) - 1;
+				mouse.y = -(event.clientY / window.innerHeight) * (2/window.devicePixelRatio) + 1;
+				raycaster.setFromCamera(mouse, that.camera);
+				var intersects = raycaster.intersectObjects(that.scene.children);
+				// var intersects = raycaster.intersectObjects(that.camera);
+				if (intersects.length > 0) {
+					let meshMap = intersects.find(it => {
+						return it.object.name=="bgPan" && it.point
+					});
+					var worldPosition = {};
+					if(meshMap && meshMap.point){
+						worldPosition = meshMap.point;
+					}
+					return worldPosition;
+				}
+			}
+			//获取当前鼠标悬浮到的哪个空间上-也即选取对应的空间
+			function getSelectArea (event) {
+				var mouse = new THREE.Vector2();
+				mouse.x = (event.clientX / window.innerWidth) * (2/window.devicePixelRatio) - 1;
+				mouse.y = -(event.clientY / window.innerHeight) * (2/window.devicePixelRatio) + 1;
+				raycaster.setFromCamera(mouse, that.camera);
+				var intersects = raycaster.intersectObjects(that.areaList);
+				// var intersects = raycaster.intersectObjects(that.camera);
+				if (intersects.length > 0) {
+					let selectArea = intersects[0].object;
+					return selectArea;
+				}
+			}
+			//鼠标右键事件
+			function contentmenu (event) {
+				event.preventDefault();
+				console.warn("***contentmenu***")
+				that.starWorldPosition = null;//清空初始点击位置
+			}
+			//释放鼠标
+			function mouseup(event) {
+				if(that.pageStatus==1){//页面处在显示态
+					if(that.moveObj){//存在移动对象-也就是用户点击过屏幕,系统拾取了移动对象
+						that.moveObj.material.opacity = 1;
+						that.moveObj = null;//清空移动对象
+					}else{
+						// cursorMove(event);//鼠标划过处理
+					}
+				}else if(that.pageStatus==2){//页面处在编辑态-即绘制状态
+					isDrawing = false;
+					that.starWorldPosition = null;//清空初始点击位置
+					that.areaList.push(that.drawAreaObject);//把用户绘制的空间添加到空间列表中
+					that.drawAreaObject = null;//清空
+					console.warn("***mouseup-that.areaList***",that.areaList)
+				}
+			}
+			//按下鼠标
+			function mousedown(event) {
+				console.warn("***mousedown***",event)
+				if(!event){
+					return false;
+				}
+				if(that.pageStatus==1){//页面处在显示态
+					if(that.cursorObj){//如果存在滑动对象-则需要拾取它-因为下一步要移动
+						that.moveObj = that.cursorObj;//声明并且赋值移动对象
+						that.moveStarPosition = getWorldPoint(event);//记录下移动对象初始点击的位置
+					}else{//点击时没有滑动对象,则需要把上一次的移动对象清空
+						that.moveObj = null;
+					}
+				}else if(that.pageStatus==2){//页面处在编辑态-即绘制状态
+					isDrawing = true;
+					let posi = getWorldPoint(event);
+					that.starWorldPosition = posi;//记录下点击的位置
+				}
+			}
+			//鼠标移动中
+			function onMouseMove(event) {
+			    // event.preventDefault();
+				if(that.pageStatus==1){//页面处在显示态
+					if(that.moveObj){//存在移动对象-也就是用户点击过屏幕,系统拾取了移动对象
+						moveObj(that.moveObj,event)
+					}else{
+						cursorMove(event);//鼠标划过处理
+					}
+				}else if(that.pageStatus==2){//页面处在编辑态
+					if (!isDrawing) return;
+					let _position = getWorldPoint(event);
+					if(!_position || !_position.x){//没有获取到坐标,可能发生了越界
+						return false;
+					}
+					if(!that.drawAreaObject){//此时需要创建drawAreaObject
+						// // 创建一个长、宽、的矩形;three.js 默认单位是米
+						let width = 1;
+						let height = 1;
+						const geometry = new THREE.PlaneGeometry(width, height);
+						
+						// 5.创建Lambert网格材质
+						const materialBasic = new THREE.MeshBasicMaterial({
+							color: 0x00ff00, // 绿色
+						});
+						// // 6.创建一个网格模型对象
+						const mesh = new THREE.Mesh(geometry, materialBasic); //网络模型对象Mesh
+						mesh.position.set(that.starWorldPosition.x + width/2, that.starWorldPosition.y - height/2, 0);
+						
+						that.drawAreaObject = mesh;
+						that.scene.add(that.drawAreaObject);
+						that.drawAreaObject.starWorldPosition = that.starWorldPosition;
+					}
+					
+					var width = _position.x - that.starWorldPosition.x;
+					var height = -(_position.y - that.starWorldPosition.y);//注意Y方向上的正方向是向上的
+								
+					that.drawAreaObject.scale.set(width, height, 1);
+					that.drawAreaObject.position.set(that.starWorldPosition.x + width / 2, that.starWorldPosition.y - height / 2, 0);
+					drawXLine(_position);	//绘制X轴提示线
+					drawYLine(_position);	//绘制Y轴提示线
+					drawArea(_position)		//绘制面积提示语
+				}
+			}
+			//绘制X轴提示线-2D position 鼠标对应的点
+			function drawXLine (position) {
+				let startPosition = that.starWorldPosition;
+				let endPosition = position;
+				//数据过滤-确保数据是正确的
+				if(!startPosition || !endPosition || !startPosition.x || !endPosition.x){
+					return false;
+				}
+				if(startPosition.x == endPosition.x){//线段的开始点和结束点不能相同
+					return false
+				}
+				let cha = 0.1;//偏移量
+				if(endPosition.y > startPosition.y){
+					cha = -0.1
+				}
+				let XLine = that.drawAreaObject.XLine;
+				if(!XLine){//如果当前绘制的空间没有X轴提示线
+					// 创建线的几何体
+					var geometry = new THREE.BufferGeometry();
+					// 初始线的顶点位置
+					var positions = new Float32Array(6);
+					positions[0] = startPosition.x; // x1
+					positions[1] = startPosition.y + cha; // y1
+					positions[2] = 0; // z1
+					positions[3] = endPosition.x; // x2
+					positions[4] = startPosition.y + cha; // y2
+					positions[5] = 0; // z2
+					// 设置线的属性
+					geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
+					const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
+					const line = new THREE.Line( geometry, material );
+					that.drawAreaObject.XLine = line;//保存X轴提示线
+					that.scene.add(line);
+				}else{
+					XLine.geometry.attributes.position.array[1] = startPosition.y + cha; // y1
+					XLine.geometry.attributes.position.array[3] = endPosition.x;
+					XLine.geometry.attributes.position.array[4] = startPosition.y + cha;
+					XLine.geometry.attributes.position.needsUpdate = true;
+				}
+				//超过1个单位的距离,才显示
+				if( Math.abs(endPosition.x - startPosition.x)/2 > 1 ){
+					if(XLine && XLine.elem){
+						XLine.elem.style.display = 'block';
+					}
+					let content = "";
+					let tempV = new THREE.Vector3();
+					tempV.x = (endPosition.x + startPosition.x)/2;
+					tempV.y = startPosition.y + cha*4;
+					tempV.z = 0;
+					content =  Math.abs(endPosition.x - startPosition.x).toFixed(2) + 'm';
+					makeTips(XLine,tempV,content)
+				}else{
+					if(XLine && XLine.elem){
+						XLine.elem.style.display = 'none';
+					}
+				}
+			}
+			//绘制Y轴提示线-2D position 鼠标对应的点
+			function drawYLine (position) {
+				let startPosition = that.starWorldPosition;
+				let endPosition = position;
+				//数据过滤-确保数据是正确的
+				if(!startPosition || !endPosition || !startPosition.y || !endPosition.y){
+					return false;
+				}
+				if(startPosition.y == endPosition.y){//线段的开始点和结束点不能相同
+					return false
+				}
+				let cha = 0.1;
+				if(endPosition.x > startPosition.x){
+					cha = -0.1
+				}
+				let YLine = that.drawAreaObject.YLine;
+				if(!YLine){//如果当前绘制的空间没有X轴提示线
+					// 创建线的几何体
+					var geometry = new THREE.BufferGeometry();
+					// 初始线的顶点位置
+					var positions = new Float32Array(6);
+					positions[0] = startPosition.x + cha; // x1
+					positions[1] = startPosition.y; // y1
+					positions[2] = 0; // z1
+					positions[3] = endPosition.x + cha; // x2
+					positions[4] = startPosition.y; // y2
+					positions[5] = 0; // z2
+					// 设置线的属性
+					geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
+					const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
+					const line = new THREE.Line( geometry, material );
+			
+					that.drawAreaObject.YLine = line;//保存X轴提示线
+					that.scene.add(line);
+				}else{
+					YLine.geometry.attributes.position.array[0] = startPosition.x + cha; // y1
+					YLine.geometry.attributes.position.array[3] = startPosition.x + cha;
+					YLine.geometry.attributes.position.array[4] = endPosition.y;
+					YLine.geometry.attributes.position.needsUpdate = true;
+				}
+				//超过1个单位的距离,才显示
+				if(Math.abs(endPosition.y - startPosition.y)/2 > 1 ){
+					if(YLine.elem){
+						YLine.elem.style.display = 'block';
+					}
+					let content = "";
+					let tempV = new THREE.Vector3();
+					tempV.x = startPosition.x + cha;
+					tempV.y = (endPosition.y + startPosition.y)/2;
+					tempV.z = 0;
+					content =  Math.abs(endPosition.y - startPosition.y).toFixed(2) + 'm';
+					makeTips(YLine,tempV,content)
+				}else{
+					if(YLine && YLine.elem){
+						YLine.elem.style.display = 'none';
+					}
+				}
+			}
+			//绘制区域面积-2D position 鼠标对应的点
+			function drawArea (position) {
+				let startPosition = that.starWorldPosition;
+				let endPosition = position;
+				let obj = that.drawAreaObject;//当前绘制的空间对象
+				//数据过滤-确保数据是正确的
+				if(!startPosition || !endPosition || !startPosition.y || !endPosition.y
+				|| !startPosition.x || !endPosition.x){
+					return false;
+				}
+				if(startPosition.y == endPosition.y || startPosition.x == endPosition.x){//线段的开始点和结束点不能相同
+					return false
+				}
+				if(Math.abs(endPosition.x - startPosition.x)/2 > 1 ){
+					let content = "";
+					let tempV = new THREE.Vector3();
+					tempV.x = (startPosition.x + endPosition.x)/2;
+					tempV.y = (startPosition.y + endPosition.y)/2;
+					tempV.z = 0;
+					content = (Math.abs(endPosition.y - startPosition.y)*Math.abs(endPosition.x - startPosition.x)).toFixed(2) + '㎡';
+					// console.log('makeTips-area', JSON.parse(JSON.stringify(tempV)),JSON.parse(JSON.stringify(endPosition)),JSON.parse(JSON.stringify(startPosition)),);
+					makeTips(obj,tempV,content)
+				}
+			}
+			//绘制和更新提示线上的距离值-单位米 point 是世界坐标系上的点位
+			function makeTips(line, point, content=null) {
+				if(!line){//如果没有提示线,则不处理
+					return false;
+				}
+				if(!line.elem){//提示线上不存在距离值div,则创建一个
+					let elem = document.createElement('div');
+					line.elem = elem;//向父级对象上添加div对象-方便父级对象找到这个div,从而操作
+					labelContainerElem.appendChild(line.elem);
+				}
+				const tempV = new THREE.Vector3();
+				tempV.x = point.x;
+				tempV.y = point.y;
+				tempV.z = point.z;
+				line.lableX = point.x;//记录下线上提示的位置
+				line.lableY = point.y;
+				// 获取标准化屏幕坐标,x和y都会在-1和1区间
+				// x = -1 表示在最左侧
+				// y = -1 表示在最底部
+				tempV.project(that.camera);
+				// window.innerWidth, window.innerHeight
+				// 将标准屏幕坐标转化为CSS坐标
+				const x = (tempV.x *  .5 + .5) * window.innerWidth;
+				const y = (tempV.y * -.5 + .5) * window.innerHeight;
+				line.elem.textContent = content?content:line.elem.textContent;//提示的文字内容
+				// 将元素移动到此位置
+				line.elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
+			}
+			//鼠标划过处理
+			function cursorMove (event) {
+				let area = getSelectArea(event);//获取鼠标划过的空间
+				if(that.cursorObj){//当前存在鼠标划过的对象
+					if(!area){//从当前滑过对象上移开
+						that.cursorObj.material.color = that.cursorMeshColor;//恢复原来颜色
+						that.cursorObj = null;
+						that.cursorMeshColor = null;
+						document.body.style.cursor = 'default';//还原鼠标样式
+					}else{//当次还存在划过的对象
+						if(that.cursorObj.uuid == area.uuid){//一致,则不处理
+							return false;
+						}else{//不同
+							that.cursorObj.material.color = that.cursorMeshColor;//恢复原来颜色
+							that.cursorObj = area;//记录下当前鼠标划过的对象;
+							that.cursorMeshColor = area.material.color.clone();//复制当前模型材质的颜色,用与取消选中时还原
+							let color = new THREE.Color(0xff9f36); // 使用sRGB颜色值
+							color.convertSRGBToLinear(); // 将颜色值转换为线性颜色值
+							area.material.color = color;//变更颜色
+							document.body.style.cursor = 'move';//修改鼠标样式
+						}
+					}
+				}else{//不存在鼠标划过的对象
+					if(!area){
+						document.body.style.cursor = 'default';//修改鼠标样式
+						return false;
+					}
+					that.cursorMeshColor = area.material.color.clone();//复制当前模型材质的颜色,用与取消选中时还原
+					that.cursorObj = area;//记录下当前鼠标划过的对象;
+					let color = new THREE.Color(0xff9f36); // 使用sRGB颜色值
+					color.convertSRGBToLinear(); // 将颜色值转换为线性颜色值
+					area.material.color = color;//修改颜色
+					document.body.style.cursor = 'move';//修改鼠标样式
+					console.warn("****cursorObj***",that.cursorObj)
+				}
+			}
+			//空间对象移动
+			function moveObj (obj,event) {
+				if(!obj || !event){
+					return false;
+				}
+				let _position = getWorldPoint(event);
+				if(!_position || !_position.x){//没有获取到坐标,可能发生了越界
+					return false;
+				}
+				let _x = _position.x - that.moveStarPosition.x;//相对上一次移动触发时的移动距离
+				let _y = _position.y - that.moveStarPosition.y;
+				if(_x==0 && _y==0){//没有变化
+					return false;
+				}
+				if(obj.adsorbLockX){//X轴吸附
+					if(_position.x <= obj.adsorDisMaxX && _position.x >= obj.adsorDisMinX ){//移动的距离没超过阈值-不实际移动
+						_x = 0;//锁定X轴,不移动
+					}else{
+						moveObjHandle(obj,-obj.adsorDisX,0);//补充移动,填补鼠标的偏移量
+						obj.adsorbLockX = false;//解锁,可以继续移动
+					}
+				}
+				if(obj.adsorbLockY){//Y轴吸附
+					if(_position.y <= obj.adsorDisMaxY && _position.y >= obj.adsorDisMinY ){//移动的距离没超过阈值-不实际移动
+						_y = 0;//锁定Y轴移动距离,不移动
+					}else{
+						moveObjHandle(obj,0,-obj.adsorDisY);//补充移动,填补鼠标的偏移量
+						obj.adsorbLockY = false;//解锁,可以继续移动
+						// console.warn("***moveObjHandle2***",_position.y,obj.adsorDisMaxY,obj.adsorDisMinY,obj.position.y)
+					}
+				}
+				// console.warn("***moveObjHandle0***",_x,_y,
+				// obj.adsorDisMaxX,obj.adsorDisMinX,
+				// obj.adsorDisMaxY,obj.adsorDisMinY,
+				// obj.adsorbLockX,obj.adsorbLockY,
+				// that.moveStarPosition.x,that.moveStarPosition.y)
+				//先移动
+				moveObjHandle(obj,_x,_y);
+				//没有锁定X轴时
+				if(!obj.adsorbLockX){//X轴吸附
+					that.moveStarPosition.x = _position.x;
+				}
+				//没有锁定Y轴时
+				if(!obj.adsorbLockY){//Y轴吸附
+					that.moveStarPosition.y = _position.y;
+				}
+				if(!obj.adsorbLockX || !obj.adsorbLockY){//当前移动对象没有锁定也即吸附
+					// that.moveStarPosition.x = _position.x;
+					// that.moveStarPosition.y = _position.y;
+					adsorbHandle(obj,_x,_y);//开始吸附处理
+				}
+			}
+			//移动对象移动处理函数
+			function moveObjHandle(obj,_x=0,_y=0){
+				//先移动
+				if(obj.XLine){//如果移动对象存在X轴提示线
+					obj.XLine.translateX(_x);
+					obj.XLine.translateY(_y);
+					let tempV = new THREE.Vector3();//文字移动后的坐标位置-世界坐标系下
+					tempV.x = obj.XLine.lableX + _x;
+					tempV.y = obj.XLine.lableY + _y;
+					tempV.z = 0;
+					makeTips(obj.XLine,tempV)
+				}
+				if(obj.YLine){//如果移动对象存在Y轴提示线
+					obj.YLine.translateX(_x);
+					obj.YLine.translateY(_y);
+					let tempV = new THREE.Vector3();//文字移动后的坐标位置-世界坐标系下
+					tempV.x = obj.YLine.lableX + _x;
+					tempV.y = obj.YLine.lableY + _y;
+					tempV.z = 0;
+					makeTips(obj.YLine,tempV)
+				}
+				if(obj.elem){//如果移动对象存在面积提示lable
+					let tempV = new THREE.Vector3();//文字移动后的坐标位置-世界坐标系下
+					tempV.x = obj.lableX + _x;
+					tempV.y = obj.lableY + _y;
+					tempV.z = 0;
+					makeTips(obj,tempV)
+				}
+				obj.translateX(_x);
+				obj.translateY(_y);
+			}
+			//吸附处理函数
+			//移动结束后进行吸附经查
+			//吸附定义如下:如果移动对象进入其他空间边界线0.5m(adsorbDis)范围内,则触发吸附
+			//吸附过程中,只要移动对象没有离开吸附区域(由adsorbDis确定),则锁定移动目标;
+			//移动对象一旦离开吸附区域,则恢复至可移动状态,同时消除偏移量,确保鼠标位置正确
+			function adsorbHandle (obj,_x,_y) {
+				let direction = {
+					horizontal:'',	//水平移动的方向
+					vertical:'',	//垂直移动的方向
+				};
+				//计算移动方向-相对上一次的
+				if(_x>0){//向右移动
+					direction.horizontal = 'right';
+				}
+				else if(_x<0){//向左移动
+					direction.horizontal = 'left';
+				}
+				if(_y>0){//向上移动-检查上边界,下边界不做检查-当前逻辑
+					direction.vertical = 'up';
+				}
+				else if(_y<0){//向下移动-检查下边界,上边界不做检查-当前逻辑
+					direction.vertical = 'down';
+				}
+				let dis = adsorbCheck(obj,direction);//吸附检查
+				if(dis.x){
+					obj.adsorbLockX = true;//X轴吸附锁定
+					if(direction.horizontal == 'left'){
+						obj.adsorDisMaxX = that.moveStarPosition.x + (that.adsorbDis - dis.x);//吸附距离
+						obj.adsorDisMinX = that.moveStarPosition.x - (that.adsorbDis + dis.x);//吸附距离
+					}else if(direction.horizontal == 'right'){
+						obj.adsorDisMaxX = that.moveStarPosition.x + (that.adsorbDis + dis.x);//吸附距离
+						obj.adsorDisMinX = that.moveStarPosition.x - (that.adsorbDis - dis.x);//吸附距离
+					}
+					obj.adsorDisX = dis.x;//对象的偏移量-相对鼠标的
+					// obj.adsorDirec = direction.horizontal;//吸附方向
+					console.warn("***moveObj-checkX1***",dis,that.moveStarPosition.x,dis,direction,obj.adsorbLockX,obj.adsorbLockY)
+				}
+				if(dis.y){
+					obj.adsorbLockY = true;//Y轴吸附锁定
+					if(direction.vertical == 'down'){
+						obj.adsorDisMaxY = that.moveStarPosition.y + (that.adsorbDis - dis.y);//吸附距离
+						obj.adsorDisMinY = that.moveStarPosition.y - (that.adsorbDis + dis.y);//吸附距离
+					}else if(direction.vertical == 'up'){
+						obj.adsorDisMaxY = that.moveStarPosition.y + (that.adsorbDis + dis.y);//吸附距离
+						obj.adsorDisMinY = that.moveStarPosition.y - (that.adsorbDis - dis.y);//吸附距离
+					}
+					obj.adsorDisY = dis.y;//对象的偏移量-相对鼠标的
+					// obj.adsorDirec = direction.vertical;//吸附方向
+					console.warn("***moveObj-checkY2***",dis,that.moveStarPosition.y,dis,direction,obj.adsorbLockX,obj.adsorbLockY)
+				}
+				if(dis.x || dis.y){
+					moveObjHandle(obj,dis.x,dis.y);//补充移动
+				}
+			}
+			//吸附检查-遍历所有绘制的空间;obj 当前操作的空间对象
+			//direction 移动的方向
+			//如果某一方向上没有变化,则不检测该方向,该方向返回为undefined
+			function adsorbCheck (obj,direction) {
+				let _areaList = that.areaList;
+				if(!_areaList || _areaList.length<2){//绘制的空间必须大于1个,检查才有意义
+					return false;
+				}
+				let _sourceX;
+				let _sourceY;
+				let _x,_y;//修正后的移动距离
+				if(direction.horizontal=='left'){//向左移动
+					_sourceX = obj.position.x - Math.abs(obj.scale.x/2);//获取右侧垂直线的X轴的值-世界坐标系
+				}else if(direction.horizontal=='right'){//向右移动
+					_sourceX = obj.position.x + Math.abs(obj.scale.x/2);//获取右侧垂直线的X轴的值-世界坐标系
+				}
+				if(direction.vertical=='up'){//向上移动
+					_sourceY = obj.position.y + Math.abs(obj.scale.y/2);//获取右侧垂直线的X轴的值-世界坐标系
+				}else if(direction.vertical=='down'){//向下移动
+					_sourceY = obj.position.y - Math.abs(obj.scale.y/2);//获取右侧垂直线的X轴的值-世界坐标系
+				}
+				
+				//获取其他空间的水平、垂直线
+				// _areaList.forEach((item,index)=>{
+				for (let item of _areaList) {
+					if(item!=obj){//其他空间对象
+						let leftX,rightX,topY,downY;
+						rightX = item.position.x + Math.abs(item.scale.x/2);//获取右侧垂直线的X轴的值-世界坐标系
+						leftX = item.position.x - Math.abs(item.scale.x/2);//获取左侧垂直线的X轴的值-世界坐标系
+						topY = item.position.y + Math.abs(item.scale.y/2);//获取up侧垂直线的X轴的值-世界坐标系
+						downY = item.position.y - Math.abs(item.scale.y/2);//获取左侧垂直线的X轴的值-世界坐标系
+						if(_sourceX != null && _x==null){//说明水平方向上有移动
+							if(Math.abs(_sourceX - rightX) < that.adsorbDis){//检查到距离差到达阈值
+								// console.warn("***adsorbDis-checkX1***",_sourceX,rightX,direction)
+								_x = rightX - _sourceX;
+							}else if(Math.abs(_sourceX - leftX) < that.adsorbDis){//检查到距离差到达阈值
+								// console.warn("***adsorbDis-checkX2***",_sourceX,leftX,direction)
+								_x = leftX - _sourceX;
+							}
+						}
+						if(_sourceY != null && _y==null){//说明垂直方向上有移动
+							if(Math.abs(_sourceY - topY) < that.adsorbDis){//检查到距离差到达阈值
+								// console.warn("***adsorbDis-checkY1***",_sourceY,topY,direction)
+								_y =  topY - _sourceY;
+							}else if(Math.abs(_sourceY - downY) < that.adsorbDis){//检查到距离差到达阈值
+								// console.warn("***adsorbDis-checkY2***",_sourceY,downY,direction)
+								_y = downY - _sourceY;
+							}
+						}
+						if(_x != null && _y != null){//表示两个方向都要检查
+							break;
+						}
+					}
+				}
+				return {x:_x,y:_y}
+			}
+			//绘制墙壁-2D
+			function drawWall () {
+				
+			}
+		},
+		destroyed() {
+			window.map && typeof window.map.destroyed === "function" && window.map.destroyed();
+			window.map = null;
+		},
+		methods: {
+			initData(area) {
+				this.area = area;
+			},
+			render() {
+				this.renderer.render(this.scene, this.camera); //单次渲染
+				this.stats.update();
+				requestAnimationFrame(this.render)
+			},
+			//操作监听
+			operateHandle(item){
+				if(!item || !item.id){
+					return false;
+				}
+				if(item.id==1){//空间新增
+					this.pageStatus = 2;
+				}
+				if(item.id==2){//空间移动
+					this.pageStatus = 1;
+				}
+				console.warn("***operateHandle***",item,this.pageStatus)
+			},
+		},
+	};
+</script>
+<style lang="css" scoped>
+	@import "./mapComponent.css";
+</style>

+ 2 - 2
src/components/mapComponent/mapComponent.html

@@ -3,7 +3,7 @@
 	<canvas id="glcanvas" width="100vw" height="100vh" ref="glcanvas">
 		你的浏览器似乎不支持或者禁用了 HTML5 <code>&lt;canvas&gt;</code> 元素。
 	</canvas>
-	<div id="labels"></div>
+	<!-- <div id="labels"></div> -->
 	<!-- 左侧操作区域 -->
-	<left-operate-comp @operateHandle="operateHandle"></left-operate-comp>
+	<!-- <left-operate-comp @operateHandle="operateHandle"></left-operate-comp> -->
 </div>

Fichier diff supprimé car celui-ci est trop grand
+ 2375 - 608
src/components/mapComponent/mapComponent.vue


+ 313 - 0
src/mixins/floorMethod.js

@@ -0,0 +1,313 @@
+// var app = getApp(); //获取应用实例
+// const util = require('@/static/utils/util.js');
+// const config = require('@/services/urlConfig.js');
+// import requestConfig from '@/services/requestConfig.js';
+import * as THREE from 'three';
+import { TWEEN } from 'three/addons/libs/tween.module.js';
+let glbWidth = 300;//空间地板模型的真实尺寸
+let glbHeight = 300;
+export default {
+	data() {
+		return {
+			gltfSpaceUrl: "https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_WoodFloor3.glb", //模型地址
+			// gltfSpaceUrl: "https://dm.static.elab-plus.com/3d/model/20230607/diban/diban.gltf", //模型地址
+			// gltfSpaceUrl: "https://dm.static.elab-plus.com/miniProgram/model/BP_L_carpet01-1.gltf", //模型地址
+			// gltfSpace1Url: "https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles01_1.gltf", //模型地址
+			gltfSpace1Url: "https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles01_3.gltf", //模型地址
+			instancedSpaceMeshList:[],//地板实例对象 当地板复杂是就会存在多个
+			spaceTypes : ["卧室","客厅","餐厅","厨房","玄关","卫生间","衣帽间","收纳","阳台","飘窗","链接空间","自定义","楼梯","花园"],
+		}
+	},
+	watch: {},
+	methods: {
+		// 加载地板模型
+		loaderSpaceArr(list){
+			if(!list || list.length==0){
+				return false;
+			}
+			this.instancedSpaceMeshList = [];
+			this.gltfSpaces = [];
+			let comlist = list.filter(it=>it.spaceType!=14);//过滤花园的空间
+			this.loaderCommonSpace(this.gltfSpaceUrl,comlist,1);
+			let arrlist = list.filter(it=>it.spaceType==14);//花园的空间
+			this.loaderCommonSpace(this.gltfSpace1Url,arrlist,2);
+		},
+		loaderCommonSpace(gltfSpaceUrl,list,type=1){
+			var that = this;
+			this.loader.load(gltfSpaceUrl,  ( gltf ) => {
+				console.log("地板模型加载成功",list)
+				// gltf.scene.receiveShadow = true;//材质是否接收阴影
+				gltf.scene.traverse((child)=> {
+					if (child.isMesh && child.visible) {
+						let instancedMesh = new THREE.InstancedMesh(child.geometry.clone(), child.material.clone(), list.length);
+						this.instancedSpaceMeshList.push(instancedMesh);
+						//设置每一块地板的实例值
+						list.forEach((obj,i)=>{
+							let positionX = obj.centerX / 100;
+							let positionY = obj.centerY / 100;
+							if(type==1){
+								// glbWidth = glbHeight = 1500;
+							}
+							let scaleX = obj.spaceWidth / glbWidth;
+							let scaleY = obj.spaceHeight / glbHeight;
+							
+							gltf.scene.position.set(positionX, 0, -positionY);
+							gltf.scene.scale.set(scaleX, 1, scaleY); 
+							gltf.scene.updateMatrixWorld();//更新世界坐标-这样,子模型也同步更新了
+							
+							instancedMesh.setMatrixAt(i, child.matrixWorld);
+							instancedMesh.instanceMatrix.needsUpdate = true;
+							let gltfSpace = that.gltfSpaces.find(gltfSpace=>gltfSpace.spaceId == obj.spaceId);//判断是否已经添加过
+							if(!gltfSpace){
+								let position = new THREE.Vector3();//当前几何体的位置参数
+								let scale = new THREE.Vector3();//当前几何体的缩放参数
+								position.set(positionX, 0, -positionY);
+								scale.set(scaleX, 1, scaleY); 
+								let md = {
+									spaceId:obj.spaceId,//模型实例的唯一标识
+									instancedMeshIndexList:[//标识网格实例数组的序号 以及 当前几何体 在网格实例的序号
+										{instancedMeshIndex: this.instancedSpaceMeshList.length - 1, instancedAtIndex : i},
+									],
+									spaceName:obj.spaceName,//几何体的id
+									spaceType:obj.spaceType,
+									position:position,
+									scale:scale,
+									isSizeLock:obj.isSizeLock,
+								};
+								that.gltfSpaces.push(md);
+							}else{//添加另外一组实例
+								gltfSpace.instancedMeshIndexList.push({
+									instancedMeshIndex:this.instancedSpaceMeshList.length - 1, instancedAtIndex:i
+								})
+							}
+						})
+						instancedMesh.userType = "mesh";
+						if(type==2){//花园
+							instancedMesh.name = "花园";
+						}else{//室内
+							instancedMesh.name = "地板";
+						}
+						instancedMesh.receiveShadow = true;//材质是否接收阴影
+						that.scene.add(instancedMesh);
+					}
+				});
+				if(false){
+					//给地板模型添加天花板-只有webgl_rxdz_roam页面需要天花板
+					list && list.forEach(obj=>{
+						if(obj.spaceType!=14){//花园不加上面的墙
+							let positionX = obj.centerX / 100;
+							let positionY = obj.centerY / 100;
+							// 天花板
+							const planeGeometry = new THREE.PlaneGeometry(obj.spaceWidth / 100,obj.spaceHeight / 100);
+							const planeMaterial = new THREE.MeshLambertMaterial({
+							    color:0xffffff,
+							});
+							const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial)
+							planeMesh.rotation.x =  Math.PI / 2 ;  // 旋转 180 度
+							planeMesh.position.set(positionX, 2.8, -positionY);
+							planeMesh.userType = "mesh";
+							that.scene.add(planeMesh);
+						}
+					})
+				}
+			});
+		},
+		//修改当前空间的面积大小
+		changeSpacesAnimOld(curSpace){
+			// 寻找地板
+			const cube = this.gltfSpaces.find((item)=>{
+			    return item.spaceId == curSpace.spaceId;
+			})
+			console.log("空间移动目标",cube.spaceId, JSON.stringify(cube.position),JSON.stringify(cube.scale),curSpace.toScaleX, curSpace.toScaleZ, curSpace.toPx, curSpace.toPz);
+			//获取地板模型的geometry实例
+			cube.instancedMeshIndexList.forEach(instanced=>{
+				let _index = instanced.instancedMeshIndex;//第一个geometry实例 在 全局InstancedMesh实例的位置
+				let instancedMesh = this.instancedSpaceMeshList[_index];//获取具体的网格实例
+				let stratMatrix = new THREE.Matrix4();//定义一个四维矩阵
+				instancedMesh.getMatrixAt(instanced.instancedAtIndex,stratMatrix);//获取当前几何体的四维矩阵到stratMatrix里面
+				
+				let endMatrix = stratMatrix.clone();//复制一个四维矩阵 
+				let scaleMatrix = new THREE.Matrix4();//定义一个缩放变化矩阵
+				let panMatrix = new THREE.Matrix4();//定义一个平移变化矩阵
+				
+				scaleMatrix.makeScale(curSpace.toScaleX / cube.scale.x,1,curSpace.toScaleZ / cube.scale.z);		//获得缩放变化矩阵
+				panMatrix.makeTranslation(curSpace.toPx - cube.position.x,0,curSpace.toPz - cube.position.z);	//获得平移变化矩阵
+				endMatrix.multiply(scaleMatrix).premultiply(panMatrix);//通过矩阵计算获得最终的矩阵
+				// console.warn("***drawModel-isAnimate-space***",JSON.stringify(endMatrix1),JSON.stringify(endMatrix),JSON.stringify(stratMatrix));
+				var tween = new TWEEN.Tween(stratMatrix.elements)
+				.to(endMatrix.elements, 2000)
+				.easing(TWEEN.Easing.Quadratic.InOut)
+				.onUpdate((matrixWorld)=> {
+					let m4 = new THREE.Matrix4();//定义一个四维矩阵
+					m4.set(...matrixWorld);//注意:四维矩阵的显示和实际计算的行列优先规则不同
+					instancedMesh.instanceMatrix.needsUpdate = true;//更新之前,必须开启开关
+					instancedMesh.setMatrixAt(instanced.instancedAtIndex,m4.transpose());//更新几何体的世界矩阵
+				}).onComplete(()=>{
+					instancedMesh.setMatrixAt(instanced.instancedAtIndex,endMatrix);//更新几何体的世界矩阵
+					this.tweenCameraAnmaChange(false)
+				});
+				// 开始动画
+				tween.start();
+				this.tweenCameraAnmaChange(true)
+				cube.position.x = curSpace.toPx;
+				cube.position.z = curSpace.toPz;
+				cube.scale.x = curSpace.toScaleX;
+				cube.scale.z = curSpace.toScaleZ;
+			});
+		},
+		//修改当前空间的面积大小-动画方案2
+		changeSpacesAnim(curSpace){
+			// 寻找地板
+			const cube = this.gltfSpaces.find((item)=>{
+			    return item.spaceId == curSpace.spaceId;
+			})
+			console.log("空间移动目标",cube.spaceId, JSON.stringify(cube.position),JSON.stringify(cube.scale),
+			curSpace.toPx, curSpace.toPz,curSpace.toScaleX, curSpace.toScaleZ);
+			//初始形变值
+			let x = cube.position.x;
+			let z = cube.position.z;
+			let scaleX = cube.scale.x;
+			let scaleZ = cube.scale.z;
+			//最终形变值
+			let toPx = curSpace.toPx;
+			let toPz = curSpace.toPz;
+			let toScaleX = curSpace.toScaleX;
+			let toScaleZ = curSpace.toScaleZ;
+			
+			let spaceInitMatrix = [];//空间动画时的初始变换矩阵
+			cube.instancedMeshIndexList.forEach(instanced=>{
+				let _index = instanced.instancedMeshIndex;//geometry实例 在 全局InstancedMesh实例的位置
+				let instancedMesh = this.instancedSpaceMeshList[_index];//获取具体的网格实例
+				let startMatrix = new THREE.Matrix4();//定义一个四维矩阵
+				instancedMesh.getMatrixAt(instanced.instancedAtIndex,startMatrix);//获取当前几何体的四维矩阵到stratMatrix里面
+				spaceInitMatrix.push({
+					index:_index,
+					matrix:startMatrix.clone(),
+				})
+			});
+			// console.warn("***cube***",cube.spaceId,Date.now(),JSON.stringify(spaceInitMatrix[0].matrix))
+			var tween = new TWEEN.Tween({
+				x: cube.position.x,
+				z: cube.position.z,
+				sx:cube.scale.x,
+				sz:cube.scale.z
+			})
+			.to({
+				x: curSpace.toPx,
+				z: curSpace.toPz,
+				sx:curSpace.toScaleX,
+				sz:curSpace.toScaleZ
+			}, 2000)
+			.easing(TWEEN.Easing.Quadratic.InOut)
+			.onUpdate((object)=> {
+				//获取地板模型的geometry实例
+				cube.instancedMeshIndexList.forEach(instanced=>{
+					let _index = instanced.instancedMeshIndex;//第一个geometry实例 在 全局InstancedMesh实例的位置
+					let instancedMesh = this.instancedSpaceMeshList[_index];//获取具体的网格实例
+					//获取对象实例的初始变换矩阵
+					let tmp = spaceInitMatrix.find(it=>it.index==_index);
+					let stratMatrix = tmp.matrix.clone();	//获取初始变换矩阵
+					let scaleMatrix = new THREE.Matrix4();	//定义一个缩放变化矩阵
+					let panMatrix = new THREE.Matrix4();	//定义一个平移变化矩阵
+					
+					scaleMatrix.makeScale(object.sx / scaleX,1,object.sz / scaleZ);	//获得缩放变化矩阵
+					panMatrix.makeTranslation(object.x - x,0,object.z - z);	//获得平移变化矩阵
+					stratMatrix.multiply(scaleMatrix).premultiply(panMatrix);//通过矩阵计算获得最终的形变矩阵
+					instancedMesh.instanceMatrix.needsUpdate = true;//更新之前,必须开启开关
+					instancedMesh.setMatrixAt(instanced.instancedAtIndex,stratMatrix);//更新几何体的世界矩阵
+				});
+			}).onComplete(()=>{//这个回调很可能会很慢
+				this.tweenCameraAnmaChange(false);
+				console.warn("***changeSpacesAnim-over***")
+			});
+			// 开始动画
+			tween.start();
+			this.tweenCameraAnmaChange(true)
+			cube.position.x = curSpace.toPx;
+			cube.position.z = curSpace.toPz;
+			cube.scale.x = curSpace.toScaleX;
+			cube.scale.z = curSpace.toScaleZ;
+		},
+		//所有空间整体缩放-同时同步到数据里面
+		allSpaceScale(){
+			const centerOffset = new THREE.Vector3(0, 0, 0); // 假设中心点在几何体的正中心
+			const scale = new THREE.Vector3(0.9, 1, 0.9); // 缩放尺度
+			//实例化的默认中心是就原点也就是0 0 0 这个点,所以centerOffset也必须是原点
+			// this.instancedMeshList.forEach((mesh)=>{
+			// 	mesh.scale.copy(scale);
+			// 	mesh.updateMatrix();
+			// 	mesh.updateMatrixWorld();
+			// 	mesh.updateMorphTargets();
+			// 	mesh.geometry.computeVertexNormals();
+			// })
+			// this.instancedSpaceMeshList.forEach((mesh)=>{
+			// 	mesh.scale.copy(scale);
+			// 	mesh.updateMatrix();
+			// 	mesh.updateMatrixWorld();
+			// 	mesh.updateMorphTargets();
+			// 	mesh.geometry.computeVertexNormals();
+			// })
+			// this.gltfLayouts.forEach((mesh)=>{
+			// 	// mesh.scale.copy(scale);
+			// })
+			
+			this.gltfSpaces.forEach(cube=>{
+				let dis = centerOffset.clone().sub(cube.position);//获得差值向量
+				// console.warn("***dis***",JSON.stringify(dis),JSON.stringify(cube.position),cube.spaceId);
+				let x = dis.x * (1 - scale.x);//x轴需要移动的距离
+				let y = dis.y * (1 - scale.y);//y轴需要移动的距离
+				let z = dis.z * (1 - scale.z);//z轴需要移动的距离
+				
+				let pi = new THREE.Vector3();//新的中心点位置
+				pi.x = cube.position.x + x;
+				pi.y = cube.position.y + y;
+				pi.z = cube.position.z + z;
+				cube.scale.x = cube.scale.x * scale.x;//修改真实的比例
+				cube.scale.z = cube.scale.z * scale.z;//
+				cube.position.copy(pi);
+				//同步信息到空间列表中
+				let sapce = this.spaceList.find(it=>{ return it.spaceId==cube.spaceId});
+				if(sapce){
+					//更新空间中心点值
+					sapce.centerX = pi.x * 100;
+					sapce.centerY = -1* pi.z * 100;
+					//更新空间宽度高度值
+					sapce.spaceWidth = cube.scale.x * glbWidth;
+					sapce.spaceHeight = cube.scale.z * glbHeight;
+				}
+				// let dir = new THREE.Vector3( 0, 10, 0 );;//当前几何体的位置参数
+				// console.warn("***dis1***",JSON.stringify(pi),JSON.stringify(dir));
+				// let length = 3;
+				// let hex = 0xff0000;
+				// let arrowHelper = new THREE.ArrowHelper( dir, pi, length, hex );
+				// this.scene.add( arrowHelper );
+				
+				//这是矩阵运算处理缩放的方法-此为数学上的方案
+				cube.instancedMeshIndexList.forEach(instanced=>{
+					let _index = instanced.instancedMeshIndex;//第一个geometry实例 在 全局InstancedMesh实例的位置
+					let instancedMesh = this.instancedSpaceMeshList[_index];//获取具体的网格实例
+					let stratMatrix = new THREE.Matrix4();//定义一个四维矩阵
+					instancedMesh.getMatrixAt(instanced.instancedAtIndex,stratMatrix);//获取当前几何体的四维矩阵到stratMatrix里面
+					let scaleMatrix = new THREE.Matrix4().makeScale(scale.x, scale.y, scale.z);
+					let inverseTranslationMatrix = new THREE.Matrix4().makeTranslation(x, y, z);
+					stratMatrix.premultiply(inverseTranslationMatrix);
+					stratMatrix.multiply(scaleMatrix);
+					instancedMesh.instanceMatrix.needsUpdate = true;
+					instancedMesh.setMatrixAt(instanced.instancedAtIndex,stratMatrix);//更新几何体的世界矩阵
+				});
+			})
+			this.$nextTick(()=>{
+				this.updateAllWallHandle();
+			})
+			setTimeout(() =>{
+				this.updataPageData();//更新数据到各个对象里面
+				this.calculateLayoutModelSize();//重新计算家具位置
+				this.updateLables();//更新lable
+				this.$nextTick(()=>{
+					this.updateCareFul();//更新精细调整里面的空间
+					this.updateSpanceData();//更新语音组件里面的空间
+				})
+			}, 100);
+		}
+	}
+}

+ 696 - 0
src/mixins/loadModel - 副本.js

@@ -0,0 +1,696 @@
+var app = getApp(); //获取应用实例
+const util = require('@/static/utils/util.js');
+const config = require('@/static/config.js');
+import modelData from '@/webgl/static/layoutModelData.js';
+// import requestConfig from '@/services/requestConfig.js';
+const THREE = requirePlugin('ThreeX');
+// import { TWEEN } from '@/webgl/jsm/libs/tween.module.min.js';
+export default {
+	data() {
+		return {
+			gltfLayouts: [],
+			instancedFurList:[],
+			arrFrunList:[],
+			promise_list:[],
+			loadFurPromise: new Promise((resolve) => {
+			    this.loadedCompleteFun = function() {
+			        console.log('家具模型接口结束');
+			        resolve()
+			    }
+			}),
+		}
+	},
+	watch: {},
+	onReady() {
+
+	},
+	methods: {
+		// 设置空间数组的墙体信息 
+		async setSpaceListWallInfo(){
+			for (let index = 0; index < this.spaceList.length; index++) {
+				let spaceWallInfo = {wallN:false, wallS:false, wallW:false, wallE:false}
+				const element = this.spaceList[index];
+		
+				const wallWIndex = this.gltfWalls.findIndex(item=>{
+					return element.spaceId == item.spaceId && item.wallDirection == "W"
+				})
+				spaceWallInfo.wallW = wallWIndex == -1 ? false : true;
+				const wallEIndex = this.gltfWalls.findIndex(item=>{
+					return element.spaceId == item.spaceId && item.wallDirection == "E"
+				})
+				spaceWallInfo.wallE = wallEIndex == -1 ? false : true;
+		
+				const wallNIndex = this.gltfWalls.findIndex(item=>{
+					return element.spaceId == item.spaceId && item.wallDirection == "N"
+				})
+				spaceWallInfo.wallN = wallNIndex == -1 ? false : true;
+				const wallSIndex = this.gltfWalls.findIndex(item=>{
+					return element.spaceId == item.spaceId && item.wallDirection == "S"
+				})
+				spaceWallInfo.wallS = wallSIndex == -1 ? false : true;
+				element.spaceWallInfo = spaceWallInfo;
+			}
+			await this.loadFurPromise;//等待解析分享者参数结束
+			this.$nextTick(() => {
+				this.calculateLayoutModelSize() // 计算模型的位置
+			})
+		},
+		// 批量获取空间模型信息
+		async getOverallArrangementDetailsList() {
+			// 设置空间数组的墙体信息
+			// this.setSpaceListWallInfo();
+			let arr = this.spaceList.map(it => it.layoutId).filter(it => it != 0);
+			let parmas = {
+				ids: arr,
+			};
+			this.loadFurPromise = new Promise((resolve, reject) => {
+				this.loadedCompleteFun = function() {
+				    console.log('家具模型接口结束');
+				    resolve()
+				}
+			})
+			let res = await requestConfig("getOverallArrangementDetailsList", parmas);
+			if (!res.success || !res.list || res.list.length == 0) {
+				return false;
+			}
+			this.promise_list = [];
+			this.arrFrunList = res.list;
+			this.furnHandle();
+		},
+		//拆分家具模型加载逻辑
+		furnHandle(){
+			let startTime = new Date().getTime();
+			let tmpList = [];//临时数据
+			this.gltfLayouts = []; //模型列表,所有空间里面的每个模型(家具)对应一条记录
+			
+			let allowSpaceId = [this.curSpaceObj.spaceId];
+			if(this.curSpaceObj.spaceId==758){//二层主卧特殊处理
+				allowSpaceId.push(735);//休闲小客厅
+			}
+			//花园类型的添加到家具加载目录里面
+			// this.spaceList.forEach(it=>{
+			// 	if(it.spaceType==14){
+			// 		allowSpaceId.push(it.spaceId);
+			// 	}
+			// })
+			this.arrFrunList.forEach(signel => {
+				let spaceId = this.spaceList.find(it => it.layoutId == signel.id).spaceId;
+				if(allowSpaceId.includes(spaceId)){//只加载允许的空间的布局,其他不加载
+					let md = JSON.parse(signel.modelJson); //获取布局里面的模型信息
+					console.warn("***布局***", md, signel.id)
+					//遍历模型信息,获取模型列表
+					for (let i = 0; i < md.modelData.length; i++) {
+						let item = md.modelData[i];
+						item.spaceId = spaceId;
+						item.layoutId = signel.id;
+						// tmpList.push(item);
+						this.promise_list.push(
+							new Promise((resolve, reject) => {
+								this.loadLayoutModelsOld(item , resolve);
+							})
+						)
+					}
+				}
+				
+			})
+			// let realFurArr = this.preFurnitureData(tmpList);//统一处理家具模型
+			// let arrLength = realFurArr.length;
+			// console.log("***realFurArr***", realFurArr);
+			// realFurArr && realFurArr.forEach((item,index) => {
+			// 	this.promise_list.push(
+			// 		new Promise((resolve, reject) => {
+			// 			this.loadLayoutModels(item, arrLength , resolve);
+			// 		})
+			// 	)
+			// });
+			Promise.all(this.promise_list).then(() => {
+				let endTime = new Date().getTime();
+				console.log("家具模型全部加载完成,时间:", endTime - startTime);
+				this.loadedCompleteFun()
+				// this.$nextTick(() => {
+				// 	this.calculateLayoutModelSize() // 计算模型的位置
+				// })
+			})
+		},
+		//预处理需要加载墙体模型的数据-减少模型请求数
+		preFurnitureData(list){
+			let realFurnitureArr = [];//家具列表
+			let dataList = [];
+			dataList = list.map(item=>{
+				let curSpace = this.spaceList.find(space=>space.spaceId==item.spaceId);
+				return this.resetModelParameters(curSpace, item);
+			})
+			dataList && dataList.forEach((item, index) => {
+				item.uniId = Date.now() + index;//唯一标识
+				//获取墙体对应的gltb模型的相关信息
+				let modelName = item.modelName;
+				// console.log("布局模型名称", modelName);
+				let layoutModel = modelData.find(it => modelName.indexOf(it.modelName) == 0); //模型地址
+				if (layoutModel && layoutModel.url) {//该数据存在模型地址
+					let object = realFurnitureArr.find(it=>it.url==layoutModel.url);
+					//列表中还没有这个数据
+					if(!object){
+						let it = {
+							url:layoutModel.url,
+							name:layoutModel.modelName,
+							list:[item],
+						}
+						realFurnitureArr.push(it)
+					}else{
+						object.list.push(item);
+					}
+				}
+			});
+			return realFurnitureArr;
+		},
+		//加载家具模型-实例化方案
+		loadLayoutModels(realData, arrLength, resolve){
+		    var that = this;
+			if(!realData.url){
+				console.warn("***家具模型不存在***",realData);
+				resolve();
+				return false;
+			}
+			that.loader.load(realData.url, ( gltf ) => {
+				// that.progress = parseInt(100/arrLength) + that.progress;
+				// if(that.progress>100){
+				// 	that.progress = 100;
+				// }
+				// that.$refs.myLoading.showLoading("加载中..." + that.progress+'%')
+				// console.log("家具加载成功",that.progress,realData,gltf);
+				gltf.scene.traverse((child)=> {
+					if (child.isMesh && child.visible) {
+						let instancedMesh = new THREE.InstancedMesh(child.geometry.clone(), child.material.clone(), realData.list.length);
+						this.instancedFurList.push(instancedMesh);
+						//realData 该模型被重复使用时的每一次的形变参数等
+						realData.list && realData.list.forEach((it,i)=>{
+							let rotationY = Math.PI / 2;
+							if (parseFloat(it.rotation) == 90) {
+								rotationY = 0;
+							}
+							if (parseFloat(it.rotation) == 180) {
+								rotationY = -Math.PI / 2;
+							}
+							if (parseFloat(it.rotation) == -90) {
+								rotationY = -Math.PI;
+							}
+							gltf.scene.rotation.y = rotationY;
+							gltf.scene.updateMatrixWorld();//更新世界坐标-这样,子模型也同步更新了
+							instancedMesh.setMatrixAt(i, child.matrixWorld);
+							instancedMesh.instanceMatrix.needsUpdate = true;
+							// instancedMesh.setColorAt(i, child.material.color);
+							// instancedMesh.instanceColor.needsUpdate = true;
+							let gltfFurn = that.gltfLayouts.find(itme=>itme.uniId==it.uniId);//判断是否已经添加过
+							if(!gltfFurn){
+								let position = new THREE.Vector3();//当前几何体的位置参数
+								let scale = new THREE.Vector3();//当前几何体的缩放参数
+								let rotation = new THREE.Vector3();//当前几何体的缩放参数
+								let md = {
+									uniId:it.uniId,//家具模型实例的唯一标识
+									spaceId:it.spaceId,
+									id:it.id,
+									instancedMeshIndexList:[//标识网格实例数组的序号 以及 当前几何体 在网格实例的序号
+										{instancedMeshIndex:this.instancedFurList.length-1,instancedAtIndex:i},
+									],
+									userData:it,
+									position:position,
+									scale:scale,
+									rotation:rotation,
+									loaded:false,
+								};
+								that.gltfLayouts.push(md);
+							}else{
+								gltfFurn.instancedMeshIndexList.push({
+									instancedMeshIndex:this.instancedFurList.length-1,instancedAtIndex:i
+								})
+							}
+						})
+						instancedMesh.userType = "layoutMesh";
+					}
+				});
+				resolve();
+			});
+		},
+		//加载模型
+		loadLayoutModelsOld(modelObj, resolve) {
+			let that = this;
+			const modelName = modelObj.modelName;
+			console.log("布局模型名称", modelName);
+			let layoutModel = modelData.find(it => modelName.indexOf(it.modelName) == 0); //模型地址
+			if (!layoutModel || !layoutModel.url) {
+				resolve();
+				return false
+			}
+			let url = layoutModel.url;
+			console.log("布局模型数据", layoutModel);
+			that.loader.load(url, (gltf) => {
+				// console.log("布局模型加载成功", gltf);
+				let model = gltf.scene; // 获取模型
+
+				model.name = layoutModel.modelName;
+				model.userType = "layoutMesh";
+				model.userData = modelObj;
+
+				// model.rotation.y =  Math.PI / 2 ;  // 旋转 90 度
+				this.gltfLayouts.push(model);
+				resolve();
+			});
+		},
+		// 计算家具的位置
+		calculateLayoutModelSize() {
+			console.log("计算家具的位置", this.gltfLayouts);
+			for (let index = 0; index < this.spaceList.length; index++) {
+				const element = this.spaceList[index];
+				const gltfLayoutModels = this.gltfLayouts.filter(item => {
+					return element.layoutId == item.userData.layoutId && element.spaceId == item.userData.spaceId;
+				})
+				//空间下不存在家具模型,则该空间不需要进行下一步处理
+				if (!gltfLayoutModels || gltfLayoutModels.length == 0) {
+					continue;
+				}
+				gltfLayoutModels.sort(function(a, b) {
+					return a.userData.level - b.userData.level
+				});
+				// console.log("对应空间ID的模型数组", this.gltfLayouts, element.spaceId, gltfLayoutModels)
+				for (let j = 0; j < gltfLayoutModels.length; j++) {
+					const cube = gltfLayoutModels[j];
+					this.drawLayoutModel(element, cube);
+				}
+			}
+		},
+		// 绘制模型
+		drawLayoutModel(curSpace, cube) {
+			const {
+				centerX,
+				spaceId
+			} = curSpace;
+			const cubeInfo = this.resetModelParameters(curSpace, cube.userData);
+			// const cubeInfo = cube.userData;
+			let centerY = curSpace.centerY * -1; // UE和ThreeJS坐标做相反
+			// 默认空间中心点
+			let positionX = centerX;
+			let positionY = centerY;
+			let rotationY = Math.PI / 2;
+			let scaleX = 1;
+			let scaleY = 1;
+			// 空间尺寸
+			let spaceWidth = curSpace.spaceWidth;
+			let spaceHeight = curSpace.spaceHeight;
+			// 模型尺寸
+			let modelWidth = cubeInfo.modelWidth;
+			let modelHeight = cubeInfo.modelHeight;
+
+			// // 判断旋转
+			if (parseFloat(cubeInfo.rotation) == 90) {
+				rotationY = 0;
+				// 交换尺寸
+				// modelWidth = cubeInfo.modelHeight;
+				// modelHeight = cubeInfo.modelWidth;
+			}
+			if (parseFloat(cubeInfo.rotation) == 180) {
+				rotationY = -Math.PI / 2;
+				// modelWidth = cubeInfo.modelHeight;
+				// modelHeight = cubeInfo.modelWidth;
+			}
+
+			if (parseFloat(cubeInfo.rotation) == -90) {
+				rotationY = -Math.PI;
+				// 交换尺寸
+				// modelWidth = cubeInfo.modelHeight;
+				// modelHeight = cubeInfo.modelWidth;
+			}
+			// 判断靠墙
+			if (cubeInfo.isStepAsideLeft == 'true') {
+				positionX = centerX - (spaceWidth / 2 - modelWidth / 2);
+				if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+					positionX = centerX - (spaceWidth / 2 - modelWidth / 2);
+				}
+				positionX += parseFloat(cubeInfo.marginLeft);
+				positionX += curSpace.spaceWallInfo.wallW ? 10 : 0;
+			}
+			if (cubeInfo.isStepAsideRight == 'true') {
+				positionX = centerX + (spaceWidth / 2 - modelHeight / 2);
+				if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+					positionX = centerX + (spaceWidth / 2 - modelWidth / 2);
+				}
+				positionX -= parseFloat(cubeInfo.marginRight);
+				positionX -= curSpace.spaceWallInfo.wallE ? 10 : 0;
+			}
+			if (cubeInfo.isStepAsideTop == 'true') {
+				positionY = centerY - (spaceHeight / 2 - modelWidth / 2);
+				if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+					positionY = centerY - (spaceHeight / 2 - modelHeight / 2);
+				}
+				
+				positionY += parseFloat(cubeInfo.marginTop);
+				positionY += curSpace.spaceWallInfo.wallN ? 10 : 0;
+			}
+			if (cubeInfo.isStepAsideBottom == 'true') {
+				positionY = centerY + (spaceHeight / 2 - modelHeight / 2);
+				if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+					positionY = centerY + (spaceHeight / 2 - modelHeight / 2);
+				}
+				
+				positionY -= parseFloat(cubeInfo.marginBottom);
+				positionY -= curSpace.spaceWallInfo.wallS ? 10 : 0;
+			}
+			// 参照物
+			if (parseInt(cubeInfo.referenceModelTop) > 0) {
+				const referenceModel = this.gltfLayouts.find(item => {
+					const layoutModelData = item.userData;
+					return layoutModelData.id == parseInt(cubeInfo.referenceModelTop) && layoutModelData
+						.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+				})
+				positionY = referenceModel.position.z * 100 + (referenceModel.userData.modelHeight / 2 + cubeInfo
+					.modelHeight / 2);
+				positionY = positionY + parseFloat(cubeInfo.marginTop);
+			}
+			if (parseInt(cubeInfo.referenceModelBottom) > 0) {
+				const referenceModel = this.gltfLayouts.find(item => {
+					const layoutModelData = item.userData;
+					return layoutModelData.id == parseInt(cubeInfo.referenceModelBottom) && layoutModelData
+						.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+				})
+				positionY = referenceModel.position.z * 100 - (referenceModel.userData.modelHeight / 2 + cubeInfo
+					.modelHeight / 2);
+				positionY = positionY - parseFloat(cubeInfo.marginBottom);
+			}
+			if (parseInt(cubeInfo.referenceModelLeft) > 0) {
+				const referenceModel = this.gltfLayouts.find(item => {
+					const layoutModelData = item.userData;
+					return layoutModelData.id == parseInt(cubeInfo.referenceModelLeft) && layoutModelData
+						.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+				})
+				positionX = referenceModel.position.x * 100 + (referenceModel.userData.modelWidth / 2 + cubeInfo
+					.modelWidth / 2);
+				positionX = positionX + parseFloat(cubeInfo.marginLeft);
+			}
+			if (parseInt(cubeInfo.referenceModelRight) > 0) {
+				const referenceModel = this.gltfLayouts.find(item => {
+					const layoutModelData = item.userData;
+					return layoutModelData.id == parseInt(cubeInfo.referenceModelRight) && layoutModelData
+						.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+				})
+				positionX = referenceModel.position.x * 100 - (referenceModel.userData.modelWidth / 2 + cubeInfo
+					.modelWidth / 2);
+				positionX = positionX - parseFloat(cubeInfo.marginRight);
+			}
+
+			if (cubeInfo.isFixedWidth == "false" || cubeInfo.isFixedHeight == "false") { // 固定尺寸
+				// 靠墙拉伸
+				if (cubeInfo.isStepAsideTop == 'true' && cubeInfo.isStepAsideBottom == 'true') {
+					// console.log("高度拉伸", spaceHeight / modelHeight)
+
+					positionY = centerY;
+
+					if (curSpace.spaceWallInfo.wallN && curSpace.spaceWallInfo.wallS) {
+						spaceHeight -= 20 + parseFloat(cubeInfo.marginTop) + parseFloat(cubeInfo.marginBottom);
+					} else if (curSpace.spaceWallInfo.wallN) {
+						spaceHeight -= 10 + parseFloat(cubeInfo.marginTop);
+						positionY += 10 / 2;
+						positionY += parseFloat(cubeInfo.marginTop) / 2;
+					} else if (curSpace.spaceWallInfo.wallS) {
+						spaceHeight -= 10 + parseFloat(cubeInfo.marginBottom);
+						positionY -= 10 / 2;
+						positionY -= parseFloat(cubeInfo.marginBottom) / 2;
+					}else {
+						spaceHeight -= parseFloat(cubeInfo.marginTop) + parseFloat(cubeInfo.marginBottom);
+						positionY += parseFloat(cubeInfo.marginTop) / 2 ;
+						positionY -= parseFloat(cubeInfo.marginBottom) / 2;
+					}
+
+					// 计算缩放
+					if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+						scaleY = spaceHeight / modelHeight;
+					} else {
+						scaleX = spaceHeight / modelHeight;
+					}
+
+				}
+
+				if (cubeInfo.isStepAsideLeft == 'true' && cubeInfo.isStepAsideRight == 'true') {
+					// console.log("宽度拉伸11111", spaceWidth / modelWidth)
+					positionX = centerX;
+
+					if (curSpace.spaceWallInfo.wallW && curSpace.spaceWallInfo.wallE) {
+						spaceWidth -= 20 + parseFloat(cubeInfo.marginLeft) + parseFloat(cubeInfo.marginRight);;
+					} else if (curSpace.spaceWallInfo.wallW) {
+						spaceWidth -= 10 + parseFloat(cubeInfo.marginLeft);
+						positionX += 10 / 2;
+						positionX += parseFloat(cubeInfo.marginLeft) / 2;
+					} else if (curSpace.spaceWallInfo.wallE) {
+						spaceWidth -= 10 + parseFloat(cubeInfo.marginRight);
+						positionX -= 10 / 2;
+						positionX -= parseFloat(cubeInfo.marginRight) / 2;
+					}else {
+						spaceWidth -= parseFloat(cubeInfo.marginLeft) + parseFloat(cubeInfo.marginRight);
+						positionX += parseFloat(cubeInfo.marginLeft) / 2;
+						positionX -= parseFloat(cubeInfo.marginRight) / 2;
+					}
+					// console.log("模型计算位置" , parseFloat(cubeInfo.rotation))
+					// 计算缩放
+					if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+						scaleX = spaceWidth / modelWidth;
+					} else {
+						scaleY = spaceWidth / modelWidth;
+					}
+
+				}
+
+				// 单个参照物和墙面拉伸
+				if (cubeInfo.isStepAsideTop == 'true' && parseInt(cubeInfo.referenceModelBottom) > 0) {
+					const referenceModel = this.gltfLayouts.find(item => {
+						const layoutModelData = item.userData;
+						return layoutModelData.id == parseInt(cubeInfo.referenceModelBottom) && layoutModelData
+							.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+					})
+					const referenceModelPositionY = referenceModel.position.z * 100 - referenceModel.userData
+						.modelHeight / 2 - parseFloat(cubeInfo.marginBottom);
+					const wallPositionY = centerY - spaceHeight / 2 + (curSpace.spaceWallInfo.wallN ? 10 : 0) +
+						parseFloat(cubeInfo.marginTop);
+
+					const newModelHeight = Math.abs(referenceModelPositionY - wallPositionY);
+					// console.log("上边拉伸", referenceModelPositionY, wallPositionY, newModelHeight)
+					if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
+						scaleY = newModelHeight / modelHeight;
+					} else {
+						scaleX = newModelHeight / modelHeight;
+					}
+					positionY = wallPositionY + newModelHeight / 2;
+				}
+
+				if (cubeInfo.isStepAsideBottom == 'true' && parseInt(cubeInfo.referenceModelTop) > 0) {
+
+					const referenceModel = this.gltfLayouts.find(item => {
+						const layoutModelData = item.userData;
+						return layoutModelData.id == parseInt(cubeInfo.referenceModelTop) && layoutModelData
+							.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+					})
+					const referenceModelPositionY = referenceModel.position.z * 100 + referenceModel.userData
+						.modelHeight / 2 + parseFloat(cubeInfo.marginTop) + (curSpace.spaceWallInfo.wallN ? 10 : 0);
+
+					const wallPositionY = centerY + spaceHeight / 2 - (curSpace.spaceWallInfo.wallS ? 10 : 0) -
+					parseFloat(cubeInfo.marginBottom);
+
+					const newModelHeight = Math.abs(referenceModelPositionY - wallPositionY);
+					if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
+						scaleY = newModelHeight / modelHeight;
+					} else {
+						scaleX = newModelHeight / modelHeight;
+					}
+					positionY = wallPositionY - newModelHeight / 2;
+
+				}
+				if (cubeInfo.isStepAsideLeft == 'true' && parseInt(cubeInfo.referenceModelRight) > 0) {
+					// console.log("左边拉伸")
+
+					const referenceModel = this.gltfLayouts.find(item => {
+						const layoutModelData = item.userData;
+						return layoutModelData.id == parseInt(cubeInfo.referenceModelRight) && layoutModelData
+							.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+					})
+					const referenceModelPositionX = referenceModel.position.x * 100 - referenceModel.userData
+						.modelWidth / 2 - parseFloat(cubeInfo.marginLeft);
+					const wallPositionX = centerX - spaceWidth / 2 + (curSpace.spaceWallInfo.wallE ? 10 : 0) +
+						parseFloat(cubeInfo.marginRight);
+
+					const newModelWidth = Math.abs(referenceModelPositionX - wallPositionX);
+					if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
+						scaleX = newModelWidth / modelWidth;
+					} else {
+						scaleY = newModelWidth / modelWidth;
+					}
+					positionX = wallPositionX + newModelWidth / 2;
+
+				}
+
+				if (cubeInfo.isStepAsideRight == 'true' && parseInt(cubeInfo.referenceModelLeft) > 0) {
+
+					const referenceModel = this.gltfLayouts.find(item => {
+						const layoutModelData = item.userData;
+						return layoutModelData.id == parseInt(cubeInfo.referenceModelLeft) && layoutModelData
+							.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+					})
+					const referenceModelPositionX = referenceModel.position.x * 100 + referenceModel.userData
+						.modelWidth / 2 + parseFloat(cubeInfo.marginLeft);
+					const wallPositionX = centerX + spaceWidth / 2 - (curSpace.spaceWallInfo.wallE ? 10 : 0) -
+						parseFloat(cubeInfo.marginRight);
+
+					const newModelWidth = Math.abs(referenceModelPositionX - wallPositionX);
+					if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
+						scaleX = newModelWidth / modelWidth;
+					} else {
+						scaleY = newModelWidth / modelWidth;
+					}
+
+					positionX = wallPositionX - newModelWidth / 2;
+
+					// console.log("右边拉伸", Math.abs(parseFloat(cubeInfo.rotation)))
+				}
+
+			}
+			// console.log("模型计算位置--", positionX, positionY)
+			// console.log("模型计算位置", cubeInfo, centerX, centerY, spaceWidth, spaceHeight, modelWidth, modelHeight, spaceId, scaleX, scaleY, rotationY)
+			let oldPosition = new THREE.Vector3();//当前几何体的位置参数
+			oldPosition.copy(cube.position);
+			cube.position.x = positionX / 100;
+			cube.position.z = positionY / 100;
+			cube.rotation.y = rotationY;
+			cube.scale.x = scaleX ;
+			cube.scale.z = scaleY;
+			if (!cube.parent) { //说明还没添加到场景中-旧版方法
+				this.scene.add(cube); //处理完毕后在加入场景中
+			}
+			if(scaleX>1 || scaleY>1){
+				console.warn("***scaleinfo***",cubeInfo.id,scaleX,scaleY,cubeInfo.modelName)
+			}
+			// this.updateInfo(cube,oldPosition,scaleX,scaleY);//实例化方法
+		},
+		//更新家具模型到页面中
+		updateInfo(cube,oldPosition,scaleX,scaleY){
+			let lay = this.gltfLayouts.find(it=>it.uniId==cube.uniId);
+			cube.instancedMeshIndexList.forEach(item=>{
+				let index = item.instancedMeshIndex;
+				let instancedMesh = this.instancedFurList[index];//网格实例对象
+				let curMeshIndex = item.instancedAtIndex;//当前家具模型在网格实例对象里面的序号
+				let stratMatrix = new THREE.Matrix4();//定义一个四维矩阵
+				instancedMesh.getMatrixAt(curMeshIndex,stratMatrix);//获取当前几何体的四维矩阵到stratMatrix里面
+				let scaleMatrix = new THREE.Matrix4();	//定义一个缩放变化矩阵
+				let panMatrix = new THREE.Matrix4();	//定义一个平移变化矩阵
+				if (!lay.loaded) { //说明还没添加到场景中
+					scaleMatrix.makeScale(scaleX,1,scaleY);	//获得缩放变化矩阵
+					panMatrix.makeTranslation(cube.position.x,0,cube.position.z);	//获得平移变化矩阵
+					stratMatrix.multiply(scaleMatrix).premultiply(panMatrix);//通过矩阵计算获得最终的形变矩阵
+					instancedMesh.instanceMatrix.needsUpdate = true;//更新之前,必须开启开关
+					instancedMesh.setMatrixAt(curMeshIndex,stratMatrix);//更新几何体的世界矩阵
+					this.scene.add(instancedMesh);
+				}else{//更新形变矩阵
+					panMatrix.makeTranslation(cube.position.x - oldPosition.x,0,cube.position.z - oldPosition.z);	//获得平移变化矩阵
+					stratMatrix.premultiply(panMatrix);//通过矩阵计算获得最终的形变矩阵
+					instancedMesh.instanceMatrix.needsUpdate = true;//更新之前,必须开启开关
+					instancedMesh.setMatrixAt(curMeshIndex,stratMatrix);//更新几何体的世界矩阵
+				}
+			})
+			lay.loaded = true;
+		},
+		// 空间布局旋转镜像重置模型约束
+		resetModelParameters(curSpace, cubeInfo) {
+			// 旋转
+			const defaultLayout = curSpace.layouts.find(item => {
+				return item.isDefault
+			})
+			if (!defaultLayout) {
+				return cubeInfo
+			}
+			let count = 0;
+			switch (parseInt(defaultLayout.layoutRotate)) {
+				case 90:
+					count = 1;
+					break;
+				case 180:
+					count = 2;
+					break;
+				case -90:
+					count = 3;
+					break;
+				default:
+					break;
+			}
+			for (let index = 0; index < count; index++) {
+				let oldCubeInfo = JSON.parse(JSON.stringify(cubeInfo))
+
+
+				oldCubeInfo.isStepAsideLeft = "false"
+				oldCubeInfo.isStepAsideTop = "false"
+				oldCubeInfo.isStepAsideRight = "false"
+				oldCubeInfo.isStepAsideBottom = "false"
+
+				oldCubeInfo.referenceModelLeft = "0"
+				oldCubeInfo.referenceModelTop = "0"
+				oldCubeInfo.referenceModelRight = "0"
+				oldCubeInfo.referenceModelBottom = "0"
+
+				oldCubeInfo.rotation = "0"
+
+				oldCubeInfo.marginLeft = "0";
+				oldCubeInfo.marginTop = "0";
+				oldCubeInfo.marginRight = "0";
+				oldCubeInfo.marginBottom = "0";
+
+				// 是否靠墙
+				if (cubeInfo.isStepAsideLeft == 'true') {
+					oldCubeInfo.isStepAsideTop = 'true'
+				}
+				if (cubeInfo.isStepAsideTop == 'true') {
+					oldCubeInfo.isStepAsideRight = 'true'
+				}
+				if (cubeInfo.isStepAsideRight == 'true') {
+					oldCubeInfo.isStepAsideBottom = 'true'
+				}
+				if (cubeInfo.isStepAsideBottom == 'true') {
+					oldCubeInfo.isStepAsideLeft = 'true'
+				}
+				// 参照物体
+				if (parseInt(cubeInfo.referenceModelLeft) > 0) {
+					oldCubeInfo.referenceModelTop = cubeInfo.referenceModelLeft;
+				}
+				if (parseInt(cubeInfo.referenceModelTop) > 0) {
+					oldCubeInfo.referenceModelRight = cubeInfo.referenceModelTop;
+				}
+				if (parseInt(cubeInfo.referenceModelRight) > 0) {
+					oldCubeInfo.referenceModelBottom = cubeInfo.referenceModelRight;
+				}
+				if (parseInt(cubeInfo.referenceModelBottom) > 0) {
+					oldCubeInfo.referenceModelLeft = cubeInfo.referenceModelBottom;
+				}
+
+				// 边距
+				oldCubeInfo.marginLeft = cubeInfo.marginTop;
+				oldCubeInfo.marginTop = cubeInfo.marginRight;
+				oldCubeInfo.marginRight = cubeInfo.marginBottom;
+				oldCubeInfo.marginBottom = cubeInfo.marginLeft;
+				oldCubeInfo.modelWidth = cubeInfo.modelHeight;
+				oldCubeInfo.modelHeight = cubeInfo.modelWidth;
+
+				// 旋转
+				if (parseInt(cubeInfo.rotation) == 0 || parseInt(cubeInfo.rotation) == 90) {
+					oldCubeInfo.rotation = parseInt(cubeInfo.rotation) + 90;
+				}
+				if (parseInt(cubeInfo.rotation) == 180) {
+					oldCubeInfo.rotation = "-90";
+				}
+				if (parseInt(cubeInfo.rotation) == -90) {
+					oldCubeInfo.rotation = "0";
+				}
+
+				// console.log("旋转前的模型参数X", cubeInfo, oldCubeInfo, defaultLayout)
+
+				cubeInfo = oldCubeInfo;
+
+				// console.log("旋转后的模型参数X", cubeInfo, oldCubeInfo, defaultLayout)
+			}
+
+			return cubeInfo;
+		},
+	}
+}

+ 713 - 0
src/mixins/loadModel.js

@@ -0,0 +1,713 @@
+// const util = require('@/static/utils/util.js');
+const config = require('@/services/urlConfig.js');
+import modelData from '@/static/layoutModelData.js';
+// import requestConfig from '@/services/requestConfig.js';
+import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
+import * as THREE from 'three';
+// import { TWEEN } from '@/webgl/jsm/libs/tween.module.min.js';
+export default {
+	data() {
+		return {
+			gltfLayouts: [],
+			instancedFurList:[],
+			arrFrunList:[],
+			promise_list:[],
+			loadFurPromise: new Promise((resolve) => {
+			    this.loadedCompleteFun = function() {
+			        console.log('家具模型接口结束');
+			        resolve()
+			    }
+			}),
+			dracoLoader:null,
+		}
+	},
+	watch: {},
+	mounted() {
+		console.warn("***loadmodel-mounted****")
+		// this.dracoLoader = new DRACOLoader();
+		// this.dracoLoader.setDecoderPath('three/addons/libs/draco/gltf/');
+		// this.dracoLoader.setDecoderConfig( { type: 'js' } );
+		// this.dracoLoader.preload();
+	},
+	methods: {
+		// 设置空间数组的墙体信息 
+		async setSpaceListWallInfo(){
+			for (let index = 0; index < this.spaceList.length; index++) {
+				let spaceWallInfo = {wallN:false, wallS:false, wallW:false, wallE:false}
+				const element = this.spaceList[index];
+		
+				const wallWIndex = this.gltfWalls.findIndex(item=>{
+					return element.spaceId == item.spaceId && item.wallDirection == "W"
+				})
+				spaceWallInfo.wallW = wallWIndex == -1 ? false : true;
+				const wallEIndex = this.gltfWalls.findIndex(item=>{
+					return element.spaceId == item.spaceId && item.wallDirection == "E"
+				})
+				spaceWallInfo.wallE = wallEIndex == -1 ? false : true;
+		
+				const wallNIndex = this.gltfWalls.findIndex(item=>{
+					return element.spaceId == item.spaceId && item.wallDirection == "N"
+				})
+				spaceWallInfo.wallN = wallNIndex == -1 ? false : true;
+				const wallSIndex = this.gltfWalls.findIndex(item=>{
+					return element.spaceId == item.spaceId && item.wallDirection == "S"
+				})
+				spaceWallInfo.wallS = wallSIndex == -1 ? false : true;
+				element.spaceWallInfo = spaceWallInfo;
+			}
+			await this.loadFurPromise;//等待解析分享者参数结束
+			this.$nextTick(() => {
+				this.calculateLayoutModelSize() // 计算模型的位置
+			})
+		},
+		// 批量获取空间模型信息
+		async getOverallArrangementDetailsList() {
+			// 设置空间数组的墙体信息
+			// this.setSpaceListWallInfo();
+			let arr = this.spaceList.map(it => it.layoutId).filter(it => it != 0);
+			let parmas = {
+				ids: arr,
+			};
+			this.loadFurPromise = new Promise((resolve, reject) => {
+				this.loadedCompleteFun = function() {
+				    console.log('家具模型接口结束');
+				    resolve()
+				}
+			})
+			let res = await requestConfig("getOverallArrangementDetailsList", parmas);
+			if (!res.success || !res.list || res.list.length == 0) {
+				return false;
+			}
+			this.promise_list = [];
+			this.arrFrunList = res.list;
+			this.furnHandle();
+		},
+		//拆分家具模型加载逻辑
+		furnHandle(){
+			let startTime = new Date().getTime();
+			let tmpList = [];//临时数据
+			this.gltfLayouts = []; //模型列表,所有空间里面的每个模型(家具)对应一条记录
+			
+			let allowSpaceId = [this.curSpaceObj.spaceId];
+			// let allowSpaceId = [];
+			if(this.curSpaceObj.spaceId==758){//二层主卧特殊处理
+				// allowSpaceId.push(735);//休闲小客厅
+			}
+			//花园类型的添加到家具加载目录里面
+			this.spaceList.forEach(it=>{
+				if(it.spaceType==14){
+					// allowSpaceId.push(it.spaceId);
+				}
+			})
+			this.arrFrunList.forEach(signel => {
+				let spaceId = this.spaceList.find(it => it.layoutId == signel.id).spaceId;
+				if(allowSpaceId.includes(spaceId)){//只加载允许的空间的布局,其他不加载
+					let md = JSON.parse(signel.modelJson); //获取布局里面的模型信息
+					console.warn("***布局***", md, signel.id)
+					//遍历模型信息,获取模型列表
+					for (let i = 0; i < md.modelData.length; i++) {
+						let item = md.modelData[i];
+						item.spaceId = spaceId;
+						item.layoutId = signel.id;
+						tmpList.push(item);
+						// this.promise_list.push(
+						// 	new Promise((resolve, reject) => {
+						// 		this.loadLayoutModelsOld(item , resolve);
+						// 	})
+						// )
+					}
+				}
+				
+			})
+			let realFurArr = this.preFurnitureData(tmpList);//统一处理家具模型
+			let arrLength = realFurArr.length;
+			console.log("***realFurArr***", realFurArr);
+			realFurArr && realFurArr.forEach((item,index) => {
+				this.promise_list.push(
+					new Promise((resolve, reject) => {
+						this.loadLayoutModels(item, arrLength , resolve);
+					})
+				)
+			});
+			Promise.all(this.promise_list).then(() => {
+				let endTime = new Date().getTime();
+				console.log("家具模型全部加载完成,时间:", endTime - startTime);
+				this.loadedCompleteFun()
+				// this.$nextTick(() => {
+				// 	this.calculateLayoutModelSize() // 计算模型的位置
+				// })
+			})
+		},
+		//预处理需要加载墙体模型的数据-减少模型请求数
+		preFurnitureData(list){
+			let realFurnitureArr = [];//家具列表
+			let dataList = [];
+			dataList = list.map(item=>{
+				let curSpace = this.spaceList.find(space=>space.spaceId==item.spaceId);
+				return this.resetModelParameters(curSpace, item);
+			})
+			dataList && dataList.forEach((item, index) => {
+				item.uniId = Date.now() + index;//唯一标识
+				//获取墙体对应的gltb模型的相关信息
+				let modelName = item.modelName;
+				// console.log("布局模型名称", modelName);
+				let layoutModel = modelData.find(it => modelName.indexOf(it.modelName) == 0); //模型地址
+				if (layoutModel && layoutModel.url) {//该数据存在模型地址
+					let object = realFurnitureArr.find(it=>it.url==layoutModel.url);
+					//列表中还没有这个数据
+					if(!object){
+						let it = {
+							url:layoutModel.url,
+							name:layoutModel.modelName,
+							list:[item],
+						}
+						realFurnitureArr.push(it)
+					}else{
+						object.list.push(item);
+					}
+				}
+			});
+			return realFurnitureArr;
+		},
+		//加载家具模型-实例化方案
+		loadLayoutModels(realData, arrLength, resolve){
+		    var that = this;
+			if(!realData.url){
+				console.warn("***家具模型不存在***",realData);
+				resolve();
+				return false;
+			}
+			that.loader.setDRACOLoader(this.dracoLoader);
+			// if(realData.url.endsWith('.glb')){
+			// 	realData.url = realData.url.replace('/model/',/dracomodel/);
+			// }
+			that.loader.load(realData.url, ( gltf ) => {
+				// that.progress = parseInt(100/arrLength) + that.progress;
+				// if(that.progress>100){
+				// 	that.progress = 100;
+				// }
+				// that.$refs.myLoading.showLoading("加载中..." + that.progress+'%')
+				// console.log("家具加载成功",that.progress,realData,gltf);
+				// gltf.scene.castShadow = true; 
+				gltf.scene.traverse((child)=> {
+					if (child.isMesh && child.visible) {
+						let instancedMesh = new THREE.InstancedMesh(child.geometry.clone(), child.material.clone(), realData.list.length);
+						this.instancedFurList.push(instancedMesh);
+						//realData 该模型被重复使用时的每一次的形变参数等
+						realData.list && realData.list.forEach((it,i)=>{
+							let rotationY = Math.PI / 2;
+							if (parseFloat(it.rotation) == 90) {
+								rotationY = 0;
+							}
+							if (parseFloat(it.rotation) == 180) {
+								rotationY = -Math.PI / 2;
+							}
+							if (parseFloat(it.rotation) == -90) {
+								rotationY = -Math.PI;
+							}
+							gltf.scene.rotation.y = rotationY;
+							gltf.scene.updateMatrixWorld();//更新世界坐标-这样,子模型也同步更新了
+							instancedMesh.setMatrixAt(i, child.matrixWorld);
+							instancedMesh.instanceMatrix.needsUpdate = true;
+							// instancedMesh.setColorAt(i, child.material.color);
+							// instancedMesh.instanceColor.needsUpdate = true;
+							let gltfFurn = that.gltfLayouts.find(itme=>itme.uniId==it.uniId);//判断是否已经添加过
+							if(!gltfFurn){
+								let position = new THREE.Vector3();//当前几何体的位置参数
+								let scale = new THREE.Vector3();//当前几何体的缩放参数
+								let rotation = new THREE.Vector3();//当前几何体的缩放参数
+								let md = {
+									uniId:it.uniId,//家具模型实例的唯一标识
+									spaceId:it.spaceId,
+									id:it.id,
+									instancedMeshIndexList:[//标识网格实例数组的序号 以及 当前几何体 在网格实例的序号
+										{instancedMeshIndex:this.instancedFurList.length-1,instancedAtIndex:i},
+									],
+									userData:it,
+									position:position,
+									scale:scale,
+									rotation:rotation,
+									loaded:false,
+								};
+								that.gltfLayouts.push(md);
+							}else{
+								gltfFurn.instancedMeshIndexList.push({
+									instancedMeshIndex:this.instancedFurList.length-1,instancedAtIndex:i
+								})
+							}
+						})
+						instancedMesh.userType = "layoutMesh";
+						if(realData.name.includes("BP_L_carpet01")){//地毯接收阴影
+							instancedMesh.receiveShadow = true;//对象是否接收阴影
+						}else{
+							instancedMesh.castShadow = true;//对象是否产生阴影
+						}
+					}
+				});
+				resolve();
+			});
+		},
+		//加载模型
+		loadLayoutModelsOld(modelObj, resolve) {
+			let that = this;
+			const modelName = modelObj.modelName;
+			console.log("布局模型名称", modelName);
+			let layoutModel = modelData.find(it => modelName.indexOf(it.modelName) == 0); //模型地址
+			if (!layoutModel || !layoutModel.url) {
+				resolve();
+				return false
+			}
+			let url = layoutModel.url;
+			console.log("布局模型数据", layoutModel);
+			that.loader.load(url, (gltf) => {
+				// console.log("布局模型加载成功", gltf);
+				let model = gltf.scene; // 获取模型
+
+				model.name = layoutModel.modelName;
+				model.userType = "layoutMesh";
+				model.userData = modelObj;
+
+				// model.rotation.y =  Math.PI / 2 ;  // 旋转 90 度
+				this.gltfLayouts.push(model);
+				resolve();
+			});
+		},
+		// 计算家具的位置
+		calculateLayoutModelSize() {
+			console.log("计算家具的位置", this.gltfLayouts);
+			for (let index = 0; index < this.spaceList.length; index++) {
+				const element = this.spaceList[index];
+				const gltfLayoutModels = this.gltfLayouts.filter(item => {
+					return element.layoutId == item.userData.layoutId && element.spaceId == item.userData.spaceId;
+				})
+				//空间下不存在家具模型,则该空间不需要进行下一步处理
+				if (!gltfLayoutModels || gltfLayoutModels.length == 0) {
+					continue;
+				}
+				gltfLayoutModels.sort(function(a, b) {
+					return a.userData.level - b.userData.level
+				});
+				// console.log("对应空间ID的模型数组", this.gltfLayouts, element.spaceId, gltfLayoutModels)
+				for (let j = 0; j < gltfLayoutModels.length; j++) {
+					const cube = gltfLayoutModels[j];
+					this.drawLayoutModel(element, cube);
+				}
+			}
+		},
+		// 绘制模型
+		drawLayoutModel(curSpace, cube) {
+			const {
+				centerX,
+				spaceId
+			} = curSpace;
+			// const cubeInfo = this.resetModelParameters(curSpace, cube.userData);
+			const cubeInfo = cube.userData;
+			let centerY = curSpace.centerY * -1; // UE和ThreeJS坐标做相反
+			// 默认空间中心点
+			let positionX = centerX;
+			let positionY = centerY;
+			// let rotationY = Math.PI / 2
+			let scaleX = 1;
+			let scaleY = 1;
+
+			// 空间尺寸
+			let spaceWidth = curSpace.spaceWidth;
+			let spaceHeight = curSpace.spaceHeight;
+			// 模型尺寸
+			let modelWidth = cubeInfo.modelWidth;
+			let modelHeight = cubeInfo.modelHeight;
+
+			// // 判断旋转
+			// if (parseFloat(cubeInfo.rotation) == 90) {
+			// 	rotationY = 0;
+			// 	// 交换尺寸
+			// 	// modelWidth = cubeInfo.modelHeight;
+			// 	// modelHeight = cubeInfo.modelWidth;
+			// }
+			// if (parseFloat(cubeInfo.rotation) == 180) {
+			// 	rotationY = -Math.PI / 2;
+			// 	// modelWidth = cubeInfo.modelHeight;
+			// 	// modelHeight = cubeInfo.modelWidth;
+			// }
+
+			// if (parseFloat(cubeInfo.rotation) == -90) {
+			// 	rotationY = -Math.PI;
+			// 	// 交换尺寸
+			// 	// modelWidth = cubeInfo.modelHeight;
+			// 	// modelHeight = cubeInfo.modelWidth;
+			// }
+			// 判断靠墙
+			if (cubeInfo.isStepAsideLeft == 'true') {
+				positionX = centerX - (spaceWidth / 2 - modelWidth / 2);
+				if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+					positionX = centerX - (spaceWidth / 2 - modelWidth / 2);
+				}
+				positionX += parseFloat(cubeInfo.marginLeft);
+				positionX += curSpace.spaceWallInfo.wallW ? 10 : 0;
+			}
+			if (cubeInfo.isStepAsideRight == 'true') {
+				positionX = centerX + (spaceWidth / 2 - modelHeight / 2);
+				if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+					positionX = centerX + (spaceWidth / 2 - modelWidth / 2);
+				}
+				positionX -= parseFloat(cubeInfo.marginRight);
+				positionX -= curSpace.spaceWallInfo.wallE ? 10 : 0;
+			}
+			if (cubeInfo.isStepAsideTop == 'true') {
+				positionY = centerY - (spaceHeight / 2 - modelWidth / 2);
+				if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+					positionY = centerY - (spaceHeight / 2 - modelHeight / 2);
+				}
+				
+				positionY += parseFloat(cubeInfo.marginTop);
+				positionY += curSpace.spaceWallInfo.wallN ? 10 : 0;
+			}
+			if (cubeInfo.isStepAsideBottom == 'true') {
+				positionY = centerY + (spaceHeight / 2 - modelHeight / 2);
+				if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+					positionY = centerY + (spaceHeight / 2 - modelHeight / 2);
+				}
+				
+				positionY -= parseFloat(cubeInfo.marginBottom);
+				positionY -= curSpace.spaceWallInfo.wallS ? 10 : 0;
+			}
+			// 参照物
+			if (parseInt(cubeInfo.referenceModelTop) > 0) {
+				const referenceModel = this.gltfLayouts.find(item => {
+					const layoutModelData = item.userData;
+					return layoutModelData.id == parseInt(cubeInfo.referenceModelTop) && layoutModelData
+						.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+				})
+				positionY = referenceModel.position.z * 100 + (referenceModel.userData.modelHeight / 2 + cubeInfo
+					.modelHeight / 2);
+				positionY = positionY + parseFloat(cubeInfo.marginTop);
+			}
+			if (parseInt(cubeInfo.referenceModelBottom) > 0) {
+				const referenceModel = this.gltfLayouts.find(item => {
+					const layoutModelData = item.userData;
+					return layoutModelData.id == parseInt(cubeInfo.referenceModelBottom) && layoutModelData
+						.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+				})
+				positionY = referenceModel.position.z * 100 - (referenceModel.userData.modelHeight / 2 + cubeInfo
+					.modelHeight / 2);
+				positionY = positionY - parseFloat(cubeInfo.marginBottom);
+			}
+			if (parseInt(cubeInfo.referenceModelLeft) > 0) {
+				const referenceModel = this.gltfLayouts.find(item => {
+					const layoutModelData = item.userData;
+					return layoutModelData.id == parseInt(cubeInfo.referenceModelLeft) && layoutModelData
+						.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+				})
+				positionX = referenceModel.position.x * 100 + (referenceModel.userData.modelWidth / 2 + cubeInfo
+					.modelWidth / 2);
+				positionX = positionX + parseFloat(cubeInfo.marginLeft);
+			}
+			if (parseInt(cubeInfo.referenceModelRight) > 0) {
+				const referenceModel = this.gltfLayouts.find(item => {
+					const layoutModelData = item.userData;
+					return layoutModelData.id == parseInt(cubeInfo.referenceModelRight) && layoutModelData
+						.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+				})
+				positionX = referenceModel.position.x * 100 - (referenceModel.userData.modelWidth / 2 + cubeInfo
+					.modelWidth / 2);
+				positionX = positionX - parseFloat(cubeInfo.marginRight);
+			}
+
+			if (cubeInfo.isFixedWidth == "false" || cubeInfo.isFixedHeight == "false") { // 固定尺寸
+				// 靠墙拉伸
+				if (cubeInfo.isStepAsideTop == 'true' && cubeInfo.isStepAsideBottom == 'true') {
+					// console.log("高度拉伸", spaceHeight / modelHeight)
+
+					positionY = centerY;
+
+					if (curSpace.spaceWallInfo.wallN && curSpace.spaceWallInfo.wallS) {
+						spaceHeight -= 20 + parseFloat(cubeInfo.marginTop) + parseFloat(cubeInfo.marginBottom);
+					} else if (curSpace.spaceWallInfo.wallN) {
+						spaceHeight -= 10 + parseFloat(cubeInfo.marginTop);
+						positionY += 10 / 2;
+						positionY += parseFloat(cubeInfo.marginTop) / 2;
+					} else if (curSpace.spaceWallInfo.wallS) {
+						spaceHeight -= 10 + parseFloat(cubeInfo.marginBottom);
+						positionY -= 10 / 2;
+						positionY -= parseFloat(cubeInfo.marginBottom) / 2;
+					}else {
+						spaceHeight -= parseFloat(cubeInfo.marginTop) + parseFloat(cubeInfo.marginBottom);
+						positionY += parseFloat(cubeInfo.marginTop) / 2 ;
+						positionY -= parseFloat(cubeInfo.marginBottom) / 2;
+					}
+
+					// 计算缩放
+					if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+						scaleY = spaceHeight / modelHeight;
+					} else {
+						scaleX = spaceHeight / modelHeight;
+					}
+
+				}
+
+				if (cubeInfo.isStepAsideLeft == 'true' && cubeInfo.isStepAsideRight == 'true') {
+					// console.log("宽度拉伸11111", spaceWidth / modelWidth)
+					positionX = centerX;
+
+					if (curSpace.spaceWallInfo.wallW && curSpace.spaceWallInfo.wallE) {
+						spaceWidth -= 20 + parseFloat(cubeInfo.marginLeft) + parseFloat(cubeInfo.marginRight);;
+					} else if (curSpace.spaceWallInfo.wallW) {
+						spaceWidth -= 10 + parseFloat(cubeInfo.marginLeft);
+						positionX += 10 / 2;
+						positionX += parseFloat(cubeInfo.marginLeft) / 2;
+					} else if (curSpace.spaceWallInfo.wallE) {
+						spaceWidth -= 10 + parseFloat(cubeInfo.marginRight);
+						positionX -= 10 / 2;
+						positionX -= parseFloat(cubeInfo.marginRight) / 2;
+					}else {
+						spaceWidth -= parseFloat(cubeInfo.marginLeft) + parseFloat(cubeInfo.marginRight);
+						positionX += parseFloat(cubeInfo.marginLeft) / 2;
+						positionX -= parseFloat(cubeInfo.marginRight) / 2;
+					}
+					// console.log("模型计算位置" , parseFloat(cubeInfo.rotation))
+					// 计算缩放
+					if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+						scaleX = spaceWidth / modelWidth;
+					} else {
+						scaleY = spaceWidth / modelWidth;
+					}
+
+				}
+
+				// 单个参照物和墙面拉伸
+				if (cubeInfo.isStepAsideTop == 'true' && parseInt(cubeInfo.referenceModelBottom) > 0) {
+					const referenceModel = this.gltfLayouts.find(item => {
+						const layoutModelData = item.userData;
+						return layoutModelData.id == parseInt(cubeInfo.referenceModelBottom) && layoutModelData
+							.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+					})
+					const referenceModelPositionY = referenceModel.position.z * 100 - referenceModel.userData
+						.modelHeight / 2 - parseFloat(cubeInfo.marginBottom);
+					const wallPositionY = centerY - spaceHeight / 2 + (curSpace.spaceWallInfo.wallN ? 10 : 0) +
+						parseFloat(cubeInfo.marginTop);
+
+					const newModelHeight = Math.abs(referenceModelPositionY - wallPositionY);
+					// console.log("上边拉伸", referenceModelPositionY, wallPositionY, newModelHeight)
+					if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
+						scaleY = newModelHeight / modelHeight;
+					} else {
+						scaleX = newModelHeight / modelHeight;
+					}
+					positionY = wallPositionY + newModelHeight / 2;
+				}
+
+				if (cubeInfo.isStepAsideBottom == 'true' && parseInt(cubeInfo.referenceModelTop) > 0) {
+
+					const referenceModel = this.gltfLayouts.find(item => {
+						const layoutModelData = item.userData;
+						return layoutModelData.id == parseInt(cubeInfo.referenceModelTop) && layoutModelData
+							.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+					})
+					const referenceModelPositionY = referenceModel.position.z * 100 + referenceModel.userData
+						.modelHeight / 2 + parseFloat(cubeInfo.marginTop) + (curSpace.spaceWallInfo.wallN ? 10 : 0);
+
+					const wallPositionY = centerY + spaceHeight / 2 - (curSpace.spaceWallInfo.wallS ? 10 : 0) -
+					parseFloat(cubeInfo.marginBottom);
+
+					const newModelHeight = Math.abs(referenceModelPositionY - wallPositionY);
+					if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
+						scaleY = newModelHeight / modelHeight;
+					} else {
+						scaleX = newModelHeight / modelHeight;
+					}
+					positionY = wallPositionY - newModelHeight / 2;
+
+				}
+				if (cubeInfo.isStepAsideLeft == 'true' && parseInt(cubeInfo.referenceModelRight) > 0) {
+					// console.log("左边拉伸")
+
+					const referenceModel = this.gltfLayouts.find(item => {
+						const layoutModelData = item.userData;
+						return layoutModelData.id == parseInt(cubeInfo.referenceModelRight) && layoutModelData
+							.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+					})
+					const referenceModelPositionX = referenceModel.position.x * 100 - referenceModel.userData
+						.modelWidth / 2 - parseFloat(cubeInfo.marginLeft);
+					const wallPositionX = centerX - spaceWidth / 2 + (curSpace.spaceWallInfo.wallE ? 10 : 0) +
+						parseFloat(cubeInfo.marginRight);
+
+					const newModelWidth = Math.abs(referenceModelPositionX - wallPositionX);
+					if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
+						scaleX = newModelWidth / modelWidth;
+					} else {
+						scaleY = newModelWidth / modelWidth;
+					}
+					positionX = wallPositionX + newModelWidth / 2;
+
+				}
+
+				if (cubeInfo.isStepAsideRight == 'true' && parseInt(cubeInfo.referenceModelLeft) > 0) {
+
+					const referenceModel = this.gltfLayouts.find(item => {
+						const layoutModelData = item.userData;
+						return layoutModelData.id == parseInt(cubeInfo.referenceModelLeft) && layoutModelData
+							.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+					})
+					const referenceModelPositionX = referenceModel.position.x * 100 + referenceModel.userData
+						.modelWidth / 2 + parseFloat(cubeInfo.marginLeft);
+					const wallPositionX = centerX + spaceWidth / 2 - (curSpace.spaceWallInfo.wallE ? 10 : 0) -
+						parseFloat(cubeInfo.marginRight);
+
+					const newModelWidth = Math.abs(referenceModelPositionX - wallPositionX);
+					if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
+						scaleX = newModelWidth / modelWidth;
+					} else {
+						scaleY = newModelWidth / modelWidth;
+					}
+
+					positionX = wallPositionX - newModelWidth / 2;
+
+					// console.log("右边拉伸", Math.abs(parseFloat(cubeInfo.rotation)))
+				}
+
+			}
+			// console.log("模型计算位置--", positionX, positionY)
+			// console.log("模型计算位置", cubeInfo, centerX, centerY, spaceWidth, spaceHeight, modelWidth, modelHeight, spaceId, scaleX, scaleY, rotationY)
+			let oldPosition = new THREE.Vector3();//当前几何体的位置参数
+			oldPosition.copy(cube.position);
+			cube.position.x = positionX / 100;
+			cube.position.z = positionY / 100;
+			// cube.rotation.y = rotationY;
+			cube.scale.x = scaleX ;
+			cube.scale.z = scaleY;
+			// if (!cube.parent) { //说明还没添加到场景中-旧版方法
+			// 	this.scene.add(cube); //处理完毕后在加入场景中
+			// }
+			// if(scaleX>1 || scaleY>1){
+			// 	console.warn("***scaleinfo***",cubeInfo.id,scaleX,scaleY,cubeInfo.modelName)
+			// }
+			this.updateInfo(cube,oldPosition,scaleX,scaleY);//实例化方法
+		},
+		//更新家具模型到页面中
+		updateInfo(cube,oldPosition,scaleX,scaleY){
+			let lay = this.gltfLayouts.find(it=>it.uniId==cube.uniId);
+			cube.instancedMeshIndexList.forEach(item=>{
+				let index = item.instancedMeshIndex;
+				let instancedMesh = this.instancedFurList[index];//网格实例对象
+				let curMeshIndex = item.instancedAtIndex;//当前家具模型在网格实例对象里面的序号
+				let stratMatrix = new THREE.Matrix4();//定义一个四维矩阵
+				instancedMesh.getMatrixAt(curMeshIndex,stratMatrix);//获取当前几何体的四维矩阵到stratMatrix里面
+				let scaleMatrix = new THREE.Matrix4();	//定义一个缩放变化矩阵
+				let panMatrix = new THREE.Matrix4();	//定义一个平移变化矩阵
+				if (!lay.loaded) { //说明还没添加到场景中
+					scaleMatrix.makeScale(scaleX,1,scaleY);	//获得缩放变化矩阵
+					panMatrix.makeTranslation(cube.position.x,0,cube.position.z);	//获得平移变化矩阵
+					stratMatrix.multiply(scaleMatrix).premultiply(panMatrix);//通过矩阵计算获得最终的形变矩阵
+					instancedMesh.instanceMatrix.needsUpdate = true;//更新之前,必须开启开关
+					instancedMesh.setMatrixAt(curMeshIndex,stratMatrix);//更新几何体的世界矩阵
+					this.scene.add(instancedMesh);
+				}else{//更新形变矩阵
+					panMatrix.makeTranslation(cube.position.x - oldPosition.x,0,cube.position.z - oldPosition.z);	//获得平移变化矩阵
+					stratMatrix.premultiply(panMatrix);//通过矩阵计算获得最终的形变矩阵
+					instancedMesh.instanceMatrix.needsUpdate = true;//更新之前,必须开启开关
+					instancedMesh.setMatrixAt(curMeshIndex,stratMatrix);//更新几何体的世界矩阵
+				}
+			})
+			lay.loaded = true;
+		},
+		// 空间布局旋转镜像重置模型约束
+		resetModelParameters(curSpace, cubeInfo) {
+			// 旋转
+			const defaultLayout = curSpace.layouts.find(item => {
+				return item.isDefault
+			})
+			if (!defaultLayout) {
+				return cubeInfo
+			}
+			let count = 0;
+			switch (parseInt(defaultLayout.layoutRotate)) {
+				case 90:
+					count = 1;
+					break;
+				case 180:
+					count = 2;
+					break;
+				case -90:
+					count = 3;
+					break;
+				default:
+					break;
+			}
+			for (let index = 0; index < count; index++) {
+				let oldCubeInfo = JSON.parse(JSON.stringify(cubeInfo))
+
+
+				oldCubeInfo.isStepAsideLeft = "false"
+				oldCubeInfo.isStepAsideTop = "false"
+				oldCubeInfo.isStepAsideRight = "false"
+				oldCubeInfo.isStepAsideBottom = "false"
+
+				oldCubeInfo.referenceModelLeft = "0"
+				oldCubeInfo.referenceModelTop = "0"
+				oldCubeInfo.referenceModelRight = "0"
+				oldCubeInfo.referenceModelBottom = "0"
+
+				oldCubeInfo.rotation = "0"
+
+				oldCubeInfo.marginLeft = "0";
+				oldCubeInfo.marginTop = "0";
+				oldCubeInfo.marginRight = "0";
+				oldCubeInfo.marginBottom = "0";
+
+				// 是否靠墙
+				if (cubeInfo.isStepAsideLeft == 'true') {
+					oldCubeInfo.isStepAsideTop = 'true'
+				}
+				if (cubeInfo.isStepAsideTop == 'true') {
+					oldCubeInfo.isStepAsideRight = 'true'
+				}
+				if (cubeInfo.isStepAsideRight == 'true') {
+					oldCubeInfo.isStepAsideBottom = 'true'
+				}
+				if (cubeInfo.isStepAsideBottom == 'true') {
+					oldCubeInfo.isStepAsideLeft = 'true'
+				}
+				// 参照物体
+				if (parseInt(cubeInfo.referenceModelLeft) > 0) {
+					oldCubeInfo.referenceModelTop = cubeInfo.referenceModelLeft;
+				}
+				if (parseInt(cubeInfo.referenceModelTop) > 0) {
+					oldCubeInfo.referenceModelRight = cubeInfo.referenceModelTop;
+				}
+				if (parseInt(cubeInfo.referenceModelRight) > 0) {
+					oldCubeInfo.referenceModelBottom = cubeInfo.referenceModelRight;
+				}
+				if (parseInt(cubeInfo.referenceModelBottom) > 0) {
+					oldCubeInfo.referenceModelLeft = cubeInfo.referenceModelBottom;
+				}
+
+				// 边距
+				oldCubeInfo.marginLeft = cubeInfo.marginTop;
+				oldCubeInfo.marginTop = cubeInfo.marginRight;
+				oldCubeInfo.marginRight = cubeInfo.marginBottom;
+				oldCubeInfo.marginBottom = cubeInfo.marginLeft;
+				oldCubeInfo.modelWidth = cubeInfo.modelHeight;
+				oldCubeInfo.modelHeight = cubeInfo.modelWidth;
+
+				// 旋转
+				if (parseInt(cubeInfo.rotation) == 0 || parseInt(cubeInfo.rotation) == 90) {
+					oldCubeInfo.rotation = parseInt(cubeInfo.rotation) + 90;
+				}
+				if (parseInt(cubeInfo.rotation) == 180) {
+					oldCubeInfo.rotation = "-90";
+				}
+				if (parseInt(cubeInfo.rotation) == -90) {
+					oldCubeInfo.rotation = "0";
+				}
+
+				// console.log("旋转前的模型参数X", cubeInfo, oldCubeInfo, defaultLayout)
+
+				cubeInfo = oldCubeInfo;
+
+				// console.log("旋转后的模型参数X", cubeInfo, oldCubeInfo, defaultLayout)
+			}
+
+			return cubeInfo;
+		},
+	}
+}

+ 705 - 0
src/mixins/loadModelOldjs

@@ -0,0 +1,705 @@
+var app = getApp(); //获取应用实例
+const util = require('@/static/utils/util.js');
+const config = require('@/static/config.js');
+import modelData from '@/webgl/static/layoutModelData.js';
+import requestConfig from '@/services/requestConfig.js';
+import { DRACOLoader } from '@/webgl/jsm/loaders/DRACOLoader.js';
+const THREE = requirePlugin('ThreeX');
+// import { TWEEN } from '@/webgl/jsm/libs/tween.module.min.js';
+export default {
+	data() {
+		return {
+			gltfLayouts: [],
+			instancedFurList:[],
+			arrFrunList:[],
+			promise_list:[],
+			loadFurPromise: new Promise((resolve) => {
+			    this.loadedCompleteFun = function() {
+			        console.log('家具模型接口结束');
+			        resolve()
+			    }
+			}),
+			dracoLoader:null,
+		}
+	},
+	watch: {},
+	onReady() {
+		this.dracoLoader = new DRACOLoader();
+		this.dracoLoader.setDecoderPath('js/libs/draco/gltf/');
+		// this.dracoLoader.setDecoderConfig( { type: 'js' } );
+	},
+	methods: {
+		// 设置空间数组的墙体信息 
+		async setSpaceListWallInfo(){
+			for (let index = 0; index < this.spaceList.length; index++) {
+				let spaceWallInfo = {wallN:false, wallS:false, wallW:false, wallE:false}
+				const element = this.spaceList[index];
+		
+				const wallWIndex = this.gltfWalls.findIndex(item=>{
+					return element.spaceId == item.spaceId && item.wallDirection == "W"
+				})
+				spaceWallInfo.wallW = wallWIndex == -1 ? false : true;
+				const wallEIndex = this.gltfWalls.findIndex(item=>{
+					return element.spaceId == item.spaceId && item.wallDirection == "E"
+				})
+				spaceWallInfo.wallE = wallEIndex == -1 ? false : true;
+		
+				const wallNIndex = this.gltfWalls.findIndex(item=>{
+					return element.spaceId == item.spaceId && item.wallDirection == "N"
+				})
+				spaceWallInfo.wallN = wallNIndex == -1 ? false : true;
+				const wallSIndex = this.gltfWalls.findIndex(item=>{
+					return element.spaceId == item.spaceId && item.wallDirection == "S"
+				})
+				spaceWallInfo.wallS = wallSIndex == -1 ? false : true;
+				element.spaceWallInfo = spaceWallInfo;
+			}
+			await this.loadFurPromise;//等待解析分享者参数结束
+			this.$nextTick(() => {
+				this.calculateLayoutModelSize() // 计算模型的位置
+			})
+		},
+		// 批量获取空间模型信息
+		async getOverallArrangementDetailsList() {
+			// 设置空间数组的墙体信息
+			// this.setSpaceListWallInfo();
+			let arr = this.spaceList.map(it => it.layoutId).filter(it => it != 0);
+			let parmas = {
+				ids: arr,
+			};
+			this.loadFurPromise = new Promise((resolve, reject) => {
+				this.loadedCompleteFun = function() {
+				    console.log('家具模型接口结束');
+				    resolve()
+				}
+			})
+			let res = await requestConfig("getOverallArrangementDetailsList", parmas);
+			if (!res.success || !res.list || res.list.length == 0) {
+				return false;
+			}
+			this.promise_list = [];
+			this.arrFrunList = res.list;
+			this.furnHandle();
+		},
+		//拆分家具模型加载逻辑
+		furnHandle(){
+			let startTime = new Date().getTime();
+			let tmpList = [];//临时数据
+			this.gltfLayouts = []; //模型列表,所有空间里面的每个模型(家具)对应一条记录
+			
+			let allowSpaceId = [this.curSpaceObj.spaceId];
+			if(this.curSpaceObj.spaceId==758){//二层主卧特殊处理
+				// allowSpaceId.push(735);//休闲小客厅
+			}
+			//花园类型的添加到家具加载目录里面
+			// this.spaceList.forEach(it=>{
+			// 	if(it.spaceType==14){
+			// 		allowSpaceId.push(it.spaceId);
+			// 	}
+			// })
+			this.arrFrunList.forEach(signel => {
+				let spaceId = this.spaceList.find(it => it.layoutId == signel.id).spaceId;
+				if(allowSpaceId.includes(spaceId)){//只加载允许的空间的布局,其他不加载
+					let md = JSON.parse(signel.modelJson); //获取布局里面的模型信息
+					console.warn("***布局***", md, signel.id)
+					//遍历模型信息,获取模型列表
+					for (let i = 0; i < md.modelData.length; i++) {
+						let item = md.modelData[i];
+						item.spaceId = spaceId;
+						item.layoutId = signel.id;
+						tmpList.push(item);
+						this.promise_list.push(
+							new Promise((resolve, reject) => {
+								this.loadLayoutModelsOld(item , resolve);
+							})
+						)
+					}
+				}
+				
+			})
+			// let realFurArr = this.preFurnitureData(tmpList);//统一处理家具模型
+			// let arrLength = realFurArr.length;
+			// console.log("***realFurArr***", realFurArr);
+			// realFurArr && realFurArr.forEach((item,index) => {
+			// 	this.promise_list.push(
+			// 		new Promise((resolve, reject) => {
+			// 			this.loadLayoutModels(item, arrLength , resolve);
+			// 		})
+			// 	)
+			// });
+			Promise.all(this.promise_list).then(() => {
+				let endTime = new Date().getTime();
+				console.log("家具模型全部加载完成,时间:", endTime - startTime);
+				this.loadedCompleteFun()
+				// this.$nextTick(() => {
+				// 	this.calculateLayoutModelSize() // 计算模型的位置
+				// })
+			})
+		},
+		//预处理需要加载墙体模型的数据-减少模型请求数
+		preFurnitureData(list){
+			let realFurnitureArr = [];//家具列表
+			let dataList = [];
+			dataList = list.map(item=>{
+				let curSpace = this.spaceList.find(space=>space.spaceId==item.spaceId);
+				return this.resetModelParameters(curSpace, item);
+			})
+			dataList && dataList.forEach((item, index) => {
+				item.uniId = Date.now() + index;//唯一标识
+				//获取墙体对应的gltb模型的相关信息
+				let modelName = item.modelName;
+				// console.log("布局模型名称", modelName);
+				let layoutModel = modelData.find(it => modelName.indexOf(it.modelName) == 0); //模型地址
+				if (layoutModel && layoutModel.url) {//该数据存在模型地址
+					let object = realFurnitureArr.find(it=>it.url==layoutModel.url);
+					//列表中还没有这个数据
+					if(!object){
+						let it = {
+							url:layoutModel.url,
+							name:layoutModel.modelName,
+							list:[item],
+						}
+						realFurnitureArr.push(it)
+					}else{
+						object.list.push(item);
+					}
+				}
+			});
+			return realFurnitureArr;
+		},
+		//加载家具模型-实例化方案
+		loadLayoutModelsnew(realData, arrLength, resolve){
+		    var that = this;
+			if(!realData.url){
+				console.warn("***家具模型不存在***",realData);
+				resolve();
+				return false;
+			}
+			// that.loader.setDRACOLoader(this.dracoLoader);
+			// if(realData.url.endsWith('.glb')){
+			// 	realData.url = realData.url.replace('/model/',/dracomodel/);
+			// }
+			that.loader.load(realData.url, ( gltf ) => {
+				// that.progress = parseInt(100/arrLength) + that.progress;
+				// if(that.progress>100){
+				// 	that.progress = 100;
+				// }
+				// that.$refs.myLoading.showLoading("加载中..." + that.progress+'%')
+				// console.log("家具加载成功",that.progress,realData,gltf);
+				gltf.scene.traverse((child)=> {
+					if (child.isMesh && child.visible) {
+						let instancedMesh = new THREE.InstancedMesh(child.geometry.clone(), child.material.clone(), realData.list.length);
+						this.instancedFurList.push(instancedMesh);
+						//realData 该模型被重复使用时的每一次的形变参数等
+						realData.list && realData.list.forEach((it,i)=>{
+							let rotationY = Math.PI / 2;
+							if (parseFloat(it.rotation) == 90) {
+								rotationY = 0;
+							}
+							if (parseFloat(it.rotation) == 180) {
+								rotationY = -Math.PI / 2;
+							}
+							if (parseFloat(it.rotation) == -90) {
+								rotationY = -Math.PI;
+							}
+							gltf.scene.rotation.y = rotationY;
+							gltf.scene.updateMatrixWorld();//更新世界坐标-这样,子模型也同步更新了
+							instancedMesh.setMatrixAt(i, child.matrixWorld);
+							instancedMesh.instanceMatrix.needsUpdate = true;
+							// instancedMesh.setColorAt(i, child.material.color);
+							// instancedMesh.instanceColor.needsUpdate = true;
+							let gltfFurn = that.gltfLayouts.find(itme=>itme.uniId==it.uniId);//判断是否已经添加过
+							if(!gltfFurn){
+								let position = new THREE.Vector3();//当前几何体的位置参数
+								let scale = new THREE.Vector3();//当前几何体的缩放参数
+								let rotation = new THREE.Vector3();//当前几何体的缩放参数
+								let md = {
+									uniId:it.uniId,//家具模型实例的唯一标识
+									spaceId:it.spaceId,
+									id:it.id,
+									instancedMeshIndexList:[//标识网格实例数组的序号 以及 当前几何体 在网格实例的序号
+										{instancedMeshIndex:this.instancedFurList.length-1,instancedAtIndex:i},
+									],
+									userData:it,
+									position:position,
+									scale:scale,
+									rotation:rotation,
+									loaded:false,
+								};
+								that.gltfLayouts.push(md);
+							}else{
+								gltfFurn.instancedMeshIndexList.push({
+									instancedMeshIndex:this.instancedFurList.length-1,instancedAtIndex:i
+								})
+							}
+						})
+						instancedMesh.userType = "layoutMesh";
+					}
+				});
+				resolve();
+			});
+		},
+		//加载模型
+		loadLayoutModelsOld(modelObj, resolve) {
+			let that = this;
+			const modelName = modelObj.modelName;
+			console.log("布局模型名称", modelName);
+			let layoutModel = modelData.find(it => modelName.indexOf(it.modelName) == 0); //模型地址
+			if (!layoutModel || !layoutModel.url) {
+				resolve();
+				return false
+			}
+			let url = layoutModel.url;
+			console.log("布局模型数据", layoutModel);
+			that.loader.load(url, (gltf) => {
+				// console.log("布局模型加载成功", gltf);
+				let model = gltf.scene; // 获取模型
+
+				model.name = layoutModel.modelName;
+				model.userType = "layoutMesh";
+				model.userData = modelObj;
+
+				// model.rotation.y =  Math.PI / 2 ;  // 旋转 90 度
+				this.gltfLayouts.push(model);
+				resolve();
+			});
+		},
+		// 计算家具的位置
+		calculateLayoutModelSize() {
+			console.log("计算家具的位置", this.gltfLayouts);
+			for (let index = 0; index < this.spaceList.length; index++) {
+				const element = this.spaceList[index];
+				const gltfLayoutModels = this.gltfLayouts.filter(item => {
+					return element.layoutId == item.userData.layoutId && element.spaceId == item.userData.spaceId;
+				})
+				//空间下不存在家具模型,则该空间不需要进行下一步处理
+				if (!gltfLayoutModels || gltfLayoutModels.length == 0) {
+					continue;
+				}
+				gltfLayoutModels.sort(function(a, b) {
+					return a.userData.level - b.userData.level
+				});
+				// console.log("对应空间ID的模型数组", this.gltfLayouts, element.spaceId, gltfLayoutModels)
+				for (let j = 0; j < gltfLayoutModels.length; j++) {
+					const cube = gltfLayoutModels[j];
+					this.drawLayoutModel(element, cube);
+				}
+			}
+		},
+		// 绘制模型
+		drawLayoutModel(curSpace, cube) {
+			const {
+				centerX,
+				spaceId
+			} = curSpace;
+			const cubeInfo = this.resetModelParameters(curSpace, cube.userData);
+			// const cubeInfo = cube.userData;
+			let centerY = curSpace.centerY * -1; // UE和ThreeJS坐标做相反
+			// 默认空间中心点
+			let positionX = centerX;
+			let positionY = centerY;
+			let rotationY = Math.PI / 2
+			let scaleX = 1;
+			let scaleY = 1;
+
+			// 空间尺寸
+			let spaceWidth = curSpace.spaceWidth;
+			let spaceHeight = curSpace.spaceHeight;
+			// 模型尺寸
+			let modelWidth = cubeInfo.modelWidth;
+			let modelHeight = cubeInfo.modelHeight;
+
+			// 判断旋转
+			if (parseFloat(cubeInfo.rotation) == 90) {
+				rotationY = 0;
+				// 交换尺寸
+				// modelWidth = cubeInfo.modelHeight;
+				// modelHeight = cubeInfo.modelWidth;
+			}
+			if (parseFloat(cubeInfo.rotation) == 180) {
+				rotationY = -Math.PI / 2;
+				// modelWidth = cubeInfo.modelHeight;
+				// modelHeight = cubeInfo.modelWidth;
+			}
+
+			if (parseFloat(cubeInfo.rotation) == -90) {
+				rotationY = -Math.PI;
+				// 交换尺寸
+				// modelWidth = cubeInfo.modelHeight;
+				// modelHeight = cubeInfo.modelWidth;
+			}
+			// 判断靠墙
+			if (cubeInfo.isStepAsideLeft == 'true') {
+				positionX = centerX - (spaceWidth / 2 - modelWidth / 2);
+				if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+					positionX = centerX - (spaceWidth / 2 - modelWidth / 2);
+				}
+				positionX += parseFloat(cubeInfo.marginLeft);
+				positionX += curSpace.spaceWallInfo.wallW ? 10 : 0;
+			}
+			if (cubeInfo.isStepAsideRight == 'true') {
+				positionX = centerX + (spaceWidth / 2 - modelHeight / 2);
+				if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+					positionX = centerX + (spaceWidth / 2 - modelWidth / 2);
+				}
+				positionX -= parseFloat(cubeInfo.marginRight);
+				positionX -= curSpace.spaceWallInfo.wallE ? 10 : 0;
+			}
+			if (cubeInfo.isStepAsideTop == 'true') {
+				positionY = centerY - (spaceHeight / 2 - modelWidth / 2);
+				if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+					positionY = centerY - (spaceHeight / 2 - modelHeight / 2);
+				}
+				
+				positionY += parseFloat(cubeInfo.marginTop);
+				positionY += curSpace.spaceWallInfo.wallN ? 10 : 0;
+			}
+			if (cubeInfo.isStepAsideBottom == 'true') {
+				positionY = centerY + (spaceHeight / 2 - modelHeight / 2);
+				if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+					positionY = centerY + (spaceHeight / 2 - modelHeight / 2);
+				}
+				
+				positionY -= parseFloat(cubeInfo.marginBottom);
+				positionY -= curSpace.spaceWallInfo.wallS ? 10 : 0;
+			}
+			// 参照物
+			if (parseInt(cubeInfo.referenceModelTop) > 0) {
+				const referenceModel = this.gltfLayouts.find(item => {
+					const layoutModelData = item.userData;
+					return layoutModelData.id == parseInt(cubeInfo.referenceModelTop) && layoutModelData
+						.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+				})
+				positionY = referenceModel.position.z * 100 + (referenceModel.userData.modelHeight / 2 + cubeInfo
+					.modelHeight / 2);
+				positionY = positionY + parseFloat(cubeInfo.marginTop);
+			}
+			if (parseInt(cubeInfo.referenceModelBottom) > 0) {
+				const referenceModel = this.gltfLayouts.find(item => {
+					const layoutModelData = item.userData;
+					return layoutModelData.id == parseInt(cubeInfo.referenceModelBottom) && layoutModelData
+						.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+				})
+				positionY = referenceModel.position.z * 100 - (referenceModel.userData.modelHeight / 2 + cubeInfo
+					.modelHeight / 2);
+				positionY = positionY - parseFloat(cubeInfo.marginBottom);
+			}
+			if (parseInt(cubeInfo.referenceModelLeft) > 0) {
+				const referenceModel = this.gltfLayouts.find(item => {
+					const layoutModelData = item.userData;
+					return layoutModelData.id == parseInt(cubeInfo.referenceModelLeft) && layoutModelData
+						.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+				})
+				positionX = referenceModel.position.x * 100 + (referenceModel.userData.modelWidth / 2 + cubeInfo
+					.modelWidth / 2);
+				positionX = positionX + parseFloat(cubeInfo.marginLeft);
+			}
+			if (parseInt(cubeInfo.referenceModelRight) > 0) {
+				const referenceModel = this.gltfLayouts.find(item => {
+					const layoutModelData = item.userData;
+					return layoutModelData.id == parseInt(cubeInfo.referenceModelRight) && layoutModelData
+						.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+				})
+				positionX = referenceModel.position.x * 100 - (referenceModel.userData.modelWidth / 2 + cubeInfo
+					.modelWidth / 2);
+				positionX = positionX - parseFloat(cubeInfo.marginRight);
+			}
+
+			if (cubeInfo.isFixedWidth == "false" || cubeInfo.isFixedHeight == "false") { // 固定尺寸
+				// 靠墙拉伸
+				if (cubeInfo.isStepAsideTop == 'true' && cubeInfo.isStepAsideBottom == 'true') {
+					// console.log("高度拉伸", spaceHeight / modelHeight)
+
+					positionY = centerY;
+
+					if (curSpace.spaceWallInfo.wallN && curSpace.spaceWallInfo.wallS) {
+						spaceHeight -= 20 + parseFloat(cubeInfo.marginTop) + parseFloat(cubeInfo.marginBottom);
+					} else if (curSpace.spaceWallInfo.wallN) {
+						spaceHeight -= 10 + parseFloat(cubeInfo.marginTop);
+						positionY += 10 / 2;
+						positionY += parseFloat(cubeInfo.marginTop) / 2;
+					} else if (curSpace.spaceWallInfo.wallS) {
+						spaceHeight -= 10 + parseFloat(cubeInfo.marginBottom);
+						positionY -= 10 / 2;
+						positionY -= parseFloat(cubeInfo.marginBottom) / 2;
+					}else {
+						spaceHeight -= parseFloat(cubeInfo.marginTop) + parseFloat(cubeInfo.marginBottom);
+						positionY += parseFloat(cubeInfo.marginTop) / 2 ;
+						positionY -= parseFloat(cubeInfo.marginBottom) / 2;
+					}
+
+					// 计算缩放
+					if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+						scaleY = spaceHeight / modelHeight;
+					} else {
+						scaleX = spaceHeight / modelHeight;
+					}
+
+				}
+
+				if (cubeInfo.isStepAsideLeft == 'true' && cubeInfo.isStepAsideRight == 'true') {
+					// console.log("宽度拉伸11111", spaceWidth / modelWidth)
+					positionX = centerX;
+
+					if (curSpace.spaceWallInfo.wallW && curSpace.spaceWallInfo.wallE) {
+						spaceWidth -= 20 + parseFloat(cubeInfo.marginLeft) + parseFloat(cubeInfo.marginRight);;
+					} else if (curSpace.spaceWallInfo.wallW) {
+						spaceWidth -= 10 + parseFloat(cubeInfo.marginLeft);
+						positionX += 10 / 2;
+						positionX += parseFloat(cubeInfo.marginLeft) / 2;
+					} else if (curSpace.spaceWallInfo.wallE) {
+						spaceWidth -= 10 + parseFloat(cubeInfo.marginRight);
+						positionX -= 10 / 2;
+						positionX -= parseFloat(cubeInfo.marginRight) / 2;
+					}else {
+						spaceWidth -= parseFloat(cubeInfo.marginLeft) + parseFloat(cubeInfo.marginRight);
+						positionX += parseFloat(cubeInfo.marginLeft) / 2;
+						positionX -= parseFloat(cubeInfo.marginRight) / 2;
+					}
+					// console.log("模型计算位置" , parseFloat(cubeInfo.rotation))
+					// 计算缩放
+					if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
+						scaleX = spaceWidth / modelWidth;
+					} else {
+						scaleY = spaceWidth / modelWidth;
+					}
+
+				}
+
+				// 单个参照物和墙面拉伸
+				if (cubeInfo.isStepAsideTop == 'true' && parseInt(cubeInfo.referenceModelBottom) > 0) {
+					const referenceModel = this.gltfLayouts.find(item => {
+						const layoutModelData = item.userData;
+						return layoutModelData.id == parseInt(cubeInfo.referenceModelBottom) && layoutModelData
+							.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+					})
+					const referenceModelPositionY = referenceModel.position.z * 100 - referenceModel.userData
+						.modelHeight / 2 - parseFloat(cubeInfo.marginBottom);
+					const wallPositionY = centerY - spaceHeight / 2 + (curSpace.spaceWallInfo.wallN ? 10 : 0) +
+						parseFloat(cubeInfo.marginTop);
+
+					const newModelHeight = Math.abs(referenceModelPositionY - wallPositionY);
+					// console.log("上边拉伸", referenceModelPositionY, wallPositionY, newModelHeight)
+					if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
+						scaleY = newModelHeight / modelHeight;
+					} else {
+						scaleX = newModelHeight / modelHeight;
+					}
+					positionY = wallPositionY + newModelHeight / 2;
+				}
+
+				if (cubeInfo.isStepAsideBottom == 'true' && parseInt(cubeInfo.referenceModelTop) > 0) {
+
+					const referenceModel = this.gltfLayouts.find(item => {
+						const layoutModelData = item.userData;
+						return layoutModelData.id == parseInt(cubeInfo.referenceModelTop) && layoutModelData
+							.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+					})
+					const referenceModelPositionY = referenceModel.position.z * 100 + referenceModel.userData
+						.modelHeight / 2 + parseFloat(cubeInfo.marginTop) + (curSpace.spaceWallInfo.wallN ? 10 : 0);
+
+					const wallPositionY = centerY + spaceHeight / 2 - (curSpace.spaceWallInfo.wallS ? 10 : 0) -
+					parseFloat(cubeInfo.marginBottom);
+
+					const newModelHeight = Math.abs(referenceModelPositionY - wallPositionY);
+					if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
+						scaleY = newModelHeight / modelHeight;
+					} else {
+						scaleX = newModelHeight / modelHeight;
+					}
+					positionY = wallPositionY - newModelHeight / 2;
+
+				}
+				if (cubeInfo.isStepAsideLeft == 'true' && parseInt(cubeInfo.referenceModelRight) > 0) {
+					// console.log("左边拉伸")
+
+					const referenceModel = this.gltfLayouts.find(item => {
+						const layoutModelData = item.userData;
+						return layoutModelData.id == parseInt(cubeInfo.referenceModelRight) && layoutModelData
+							.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+					})
+					const referenceModelPositionX = referenceModel.position.x * 100 - referenceModel.userData
+						.modelWidth / 2 - parseFloat(cubeInfo.marginLeft);
+					const wallPositionX = centerX - spaceWidth / 2 + (curSpace.spaceWallInfo.wallE ? 10 : 0) +
+						parseFloat(cubeInfo.marginRight);
+
+					const newModelWidth = Math.abs(referenceModelPositionX - wallPositionX);
+					if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
+						scaleX = newModelWidth / modelWidth;
+					} else {
+						scaleY = newModelWidth / modelWidth;
+					}
+					positionX = wallPositionX + newModelWidth / 2;
+
+				}
+
+				if (cubeInfo.isStepAsideRight == 'true' && parseInt(cubeInfo.referenceModelLeft) > 0) {
+
+					const referenceModel = this.gltfLayouts.find(item => {
+						const layoutModelData = item.userData;
+						return layoutModelData.id == parseInt(cubeInfo.referenceModelLeft) && layoutModelData
+							.spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
+					})
+					const referenceModelPositionX = referenceModel.position.x * 100 + referenceModel.userData
+						.modelWidth / 2 + parseFloat(cubeInfo.marginLeft);
+					const wallPositionX = centerX + spaceWidth / 2 - (curSpace.spaceWallInfo.wallE ? 10 : 0) -
+						parseFloat(cubeInfo.marginRight);
+
+					const newModelWidth = Math.abs(referenceModelPositionX - wallPositionX);
+					if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
+						scaleX = newModelWidth / modelWidth;
+					} else {
+						scaleY = newModelWidth / modelWidth;
+					}
+
+					positionX = wallPositionX - newModelWidth / 2;
+
+					// console.log("右边拉伸", Math.abs(parseFloat(cubeInfo.rotation)))
+				}
+
+			}
+			// console.log("模型计算位置--", positionX, positionY)
+			// console.log("模型计算位置", cubeInfo, centerX, centerY, spaceWidth, spaceHeight, modelWidth, modelHeight, spaceId, scaleX, scaleY, rotationY)
+			let oldPosition = new THREE.Vector3();//当前几何体的位置参数
+			oldPosition.copy(cube.position);
+			cube.position.x = positionX / 100;
+			cube.position.z = positionY / 100;
+			cube.rotation.y = rotationY;
+			cube.scale.x = scaleX ;
+			cube.scale.z = scaleY;
+			if (!cube.parent) { //说明还没添加到场景中-旧版方法
+				this.scene.add(cube); //处理完毕后在加入场景中
+			}
+			// if(scaleX>1 || scaleY>1){
+			// 	console.warn("***scaleinfo***",cubeInfo.id,scaleX,scaleY,cubeInfo.modelName)
+			// }
+			// this.updateInfo(cube,oldPosition,scaleX,scaleY);//实例化方法
+		},
+		//更新家具模型到页面中
+		updateInfo(cube,oldPosition,scaleX,scaleY){
+			let lay = this.gltfLayouts.find(it=>it.uniId==cube.uniId);
+			cube.instancedMeshIndexList.forEach(item=>{
+				let index = item.instancedMeshIndex;
+				let instancedMesh = this.instancedFurList[index];//网格实例对象
+				let curMeshIndex = item.instancedAtIndex;//当前家具模型在网格实例对象里面的序号
+				let stratMatrix = new THREE.Matrix4();//定义一个四维矩阵
+				instancedMesh.getMatrixAt(curMeshIndex,stratMatrix);//获取当前几何体的四维矩阵到stratMatrix里面
+				let scaleMatrix = new THREE.Matrix4();	//定义一个缩放变化矩阵
+				let panMatrix = new THREE.Matrix4();	//定义一个平移变化矩阵
+				if (!lay.loaded) { //说明还没添加到场景中
+					scaleMatrix.makeScale(scaleX,1,scaleY);	//获得缩放变化矩阵
+					panMatrix.makeTranslation(cube.position.x,0,cube.position.z);	//获得平移变化矩阵
+					stratMatrix.multiply(scaleMatrix).premultiply(panMatrix);//通过矩阵计算获得最终的形变矩阵
+					instancedMesh.instanceMatrix.needsUpdate = true;//更新之前,必须开启开关
+					instancedMesh.setMatrixAt(curMeshIndex,stratMatrix);//更新几何体的世界矩阵
+					this.scene.add(instancedMesh);
+				}else{//更新形变矩阵
+					panMatrix.makeTranslation(cube.position.x - oldPosition.x,0,cube.position.z - oldPosition.z);	//获得平移变化矩阵
+					stratMatrix.premultiply(panMatrix);//通过矩阵计算获得最终的形变矩阵
+					instancedMesh.instanceMatrix.needsUpdate = true;//更新之前,必须开启开关
+					instancedMesh.setMatrixAt(curMeshIndex,stratMatrix);//更新几何体的世界矩阵
+				}
+			})
+			lay.loaded = true;
+		},
+		// 空间布局旋转镜像重置模型约束
+		resetModelParameters(curSpace, cubeInfo) {
+			// 旋转
+			const defaultLayout = curSpace.layouts.find(item => {
+				return item.isDefault
+			})
+			if (!defaultLayout) {
+				return cubeInfo
+			}
+			let count = 0;
+			switch (parseInt(defaultLayout.layoutRotate)) {
+				case 90:
+					count = 1;
+					break;
+				case 180:
+					count = 2;
+					break;
+				case -90:
+					count = 3;
+					break;
+				default:
+					break;
+			}
+			for (let index = 0; index < count; index++) {
+				let oldCubeInfo = JSON.parse(JSON.stringify(cubeInfo))
+
+
+				oldCubeInfo.isStepAsideLeft = "false"
+				oldCubeInfo.isStepAsideTop = "false"
+				oldCubeInfo.isStepAsideRight = "false"
+				oldCubeInfo.isStepAsideBottom = "false"
+
+				oldCubeInfo.referenceModelLeft = "0"
+				oldCubeInfo.referenceModelTop = "0"
+				oldCubeInfo.referenceModelRight = "0"
+				oldCubeInfo.referenceModelBottom = "0"
+
+				oldCubeInfo.rotation = "0"
+
+				oldCubeInfo.marginLeft = "0";
+				oldCubeInfo.marginTop = "0";
+				oldCubeInfo.marginRight = "0";
+				oldCubeInfo.marginBottom = "0";
+
+				// 是否靠墙
+				if (cubeInfo.isStepAsideLeft == 'true') {
+					oldCubeInfo.isStepAsideTop = 'true'
+				}
+				if (cubeInfo.isStepAsideTop == 'true') {
+					oldCubeInfo.isStepAsideRight = 'true'
+				}
+				if (cubeInfo.isStepAsideRight == 'true') {
+					oldCubeInfo.isStepAsideBottom = 'true'
+				}
+				if (cubeInfo.isStepAsideBottom == 'true') {
+					oldCubeInfo.isStepAsideLeft = 'true'
+				}
+				// 参照物体
+				if (parseInt(cubeInfo.referenceModelLeft) > 0) {
+					oldCubeInfo.referenceModelTop = cubeInfo.referenceModelLeft;
+				}
+				if (parseInt(cubeInfo.referenceModelTop) > 0) {
+					oldCubeInfo.referenceModelRight = cubeInfo.referenceModelTop;
+				}
+				if (parseInt(cubeInfo.referenceModelRight) > 0) {
+					oldCubeInfo.referenceModelBottom = cubeInfo.referenceModelRight;
+				}
+				if (parseInt(cubeInfo.referenceModelBottom) > 0) {
+					oldCubeInfo.referenceModelLeft = cubeInfo.referenceModelBottom;
+				}
+
+				// 边距
+				oldCubeInfo.marginLeft = cubeInfo.marginTop;
+				oldCubeInfo.marginTop = cubeInfo.marginRight;
+				oldCubeInfo.marginRight = cubeInfo.marginBottom;
+				oldCubeInfo.marginBottom = cubeInfo.marginLeft;
+				oldCubeInfo.modelWidth = cubeInfo.modelHeight;
+				oldCubeInfo.modelHeight = cubeInfo.modelWidth;
+
+				// 旋转
+				if (parseInt(cubeInfo.rotation) == 0 || parseInt(cubeInfo.rotation) == 90) {
+					oldCubeInfo.rotation = parseInt(cubeInfo.rotation) + 90;
+				}
+				if (parseInt(cubeInfo.rotation) == 180) {
+					oldCubeInfo.rotation = "-90";
+				}
+				if (parseInt(cubeInfo.rotation) == -90) {
+					oldCubeInfo.rotation = "0";
+				}
+
+				// console.log("旋转前的模型参数X", cubeInfo, oldCubeInfo, defaultLayout)
+
+				cubeInfo = oldCubeInfo;
+
+				// console.log("旋转后的模型参数X", cubeInfo, oldCubeInfo, defaultLayout)
+			}
+
+			return cubeInfo;
+		},
+	}
+}

+ 151 - 0
src/mixins/screenshot.js

@@ -0,0 +1,151 @@
+// const util = require('@/static/utils/util.js');
+const config = require('@/services/urlConfig.js');
+// import requestConfig from '@/services/requestConfig.js';
+// import { GLTFLoader } from '@/webgl/jsm/loaders/GLTFLoader.js';
+export default {
+	data() {
+		return {
+			canvas2d: null,
+		}
+	},
+	watch: {},
+	onReady() {
+		// wx.createSelectorQuery().select('#canvas').fields({ node: true, size: true }).exec((res) => {
+		//     this.canvas2d = res[0].node
+		// })
+	},
+	methods: {
+		//触发主页面的截屏动作
+		screenPromiseShot() {
+			let currUniPage = getCurrentPages()[getCurrentPages().length - 1].$vm;
+			return new Promise(resolve => {
+				currUniPage.screenshotResolve = resolve
+			})
+		},
+		//转base64
+		base64src(base64data, fun){
+			const base64 = base64data; //base64格式图片
+			const time = new Date().getTime();
+			const imgPath = wx.env.USER_DATA_PATH + "/4DImage/" + util.formatDate(new Date(), "yyyyMMddhhmmss") + ".jpg";
+			//如果图片字符串不含要清空的前缀,可以不执行下行代码.
+			const imageData = base64.replace(/^data:image\/\w+;base64,/, "");
+			const file = wx.getFileSystemManager();
+			// console.warn("***base64src***",base64data)
+			file.writeFileSync(imgPath, imageData, "base64");
+			fun(imgPath);
+		},
+		// 翻转Y轴-像素方案
+		flip(pixels, w, h, c) {
+			// handle Arrays
+			if (Array.isArray(pixels)) {
+				var result = this.flip(new Float64Array(pixels), w, h, c);
+				for (var i = 0; i < pixels.length; i++) {
+					pixels[i] = result[i];
+				}
+				return pixels;
+			}
+		
+			if (!w || !h) throw Error('Bad dimensions');
+			if (!c) c = pixels.length / (w * h);
+		
+			var h2 = h >> 1;
+			var row = w * c;
+			var Ctor = pixels.constructor;
+		
+			// make a temp buffer to hold one row
+			var temp = new Ctor(w * c);
+			for (var y = 0; y < h2; ++y) {
+				var topOffset = y * row;
+				var bottomOffset = (h - y - 1) * row;
+				// make copy of a row on the top half
+				temp.set(pixels.subarray(topOffset, topOffset + row));
+				// copy a row from the bottom half to the top
+				pixels.copyWithin(topOffset, bottomOffset, bottomOffset + row);
+				// copy the copy of the top half row to the bottom half
+				pixels.set(temp, bottomOffset);
+			}
+		},
+		/**
+		 * 截图
+		 */
+		async shottingAction(type=1) {
+			let currUniPage = getCurrentPages()[getCurrentPages().length - 1].$vm;
+			//时机合适时-像素存在则触发生成
+			return new Promise(resolve => {
+				this.screenPromiseShot().then((param) => {
+					if(param){
+						this.flip(param[0], param[1], param[2], 4);
+						const canvas = currUniPage.canvas2d;
+						const ctx = canvas.getContext('2d');
+						//  ImageData 对象,data是像素 一维数组,包含以 RGBA 顺序的数据,数据使用 0 至 255(包含)的整数表示
+						const img = canvas.createImageData(param[0], param[1], param[2]);
+						canvas.height = img.height;
+						canvas.width = img.width;
+						ctx.putImageData(img, 0, 0);
+						uni.canvasToTempFilePath({
+							x: 0,
+							y: 0,
+							destWidth:  canvas.width,
+							destHeight: canvas.height,
+							canvasId: "canvas",
+							canvas: canvas,
+							fileType: 'jpg',
+							quality: 1,
+							success: (res)=> {
+								console.log("***canvasToTempFilePath-success***", res)
+								this.upload(res.tempFilePath,resolve);
+							},
+							fail: (res)=> {
+								console.warn("***canvasToTempFilePath-fail***", res);
+								if(currUniPage && currUniPage.starRender && typeof(currUniPage.starRender)=='function'){
+									currUniPage.starRender()//启动渲染
+								}
+								resolve('')
+							}
+						})
+					}else{
+						let imgBase64 = this.canvas.toDataURL();
+						this.base64src(imgBase64, (res) => {
+							console.warn('转化后的url:', res)
+							this.upload(res,resolve);
+						})
+					}					
+				})
+			})
+		},
+		//上传图片
+		async upload(filePath, cb = null) {
+			var fileName = "4DImage/" + util.formatDate(new Date(), "yyyyMMddhhmmss") + '.jpg';
+			let tokenObj = await requestConfig("getUploadToken", {});
+			console.log("tokenObj:", tokenObj);
+			var token = tokenObj.single.token;
+			var resultUrl = tokenObj.single.resultUrl; //上传图片的访问前缀this.resultUrl =
+			let currUniPage = getCurrentPages()[getCurrentPages().length - 1].$vm;
+			uni.uploadFile({
+				url: "https://up.qiniup.com",
+				filePath: filePath,
+				name: "file",
+				formData: {
+					key: fileName,
+					token: token,
+				},
+				success: (uploadFileRes) => {
+					let obj = JSON.parse(uploadFileRes.data);
+					let shottingImg = resultUrl + obj.key;
+					console.warn("***截图图片***", shottingImg);
+					if (cb ) {
+						cb(shottingImg)
+					}
+				},
+				fail: (error) => {
+					cb("")
+				},
+				complete(e) {
+					if(currUniPage && currUniPage.starRender && typeof(currUniPage.starRender)=='function'){
+						currUniPage.starRender()//截图成功后,启动渲染
+					}
+				}
+			});
+		},
+	}
+}

Fichier diff supprimé car celui-ci est trop grand
+ 1048 - 0
src/mixins/wallMethod.js


+ 5 - 5
src/services/request.js

@@ -3,7 +3,7 @@ import axios from 'axios';
 import {getStorage, removeItem} from '@/utils/localStorage'
 import router from '@/router'
 var requestCount = 0; //记录下同时的请求数
-import ElementUI from 'element-ui';
+// import ElementUI from 'element-ui';
 var showToast = true;
 
 axios.defaults.headers.post['elabEnvironment'] = '4'; //axios默认的请求方式,可以自己设置
@@ -70,10 +70,10 @@ axios.interceptors.response.use(function(response) {
 		});
 		if (showToast){
 			showToast = false;
-			ElementUI.Message({
-				message:"账号已失效",
-				type:"error"
-			});
+			// ElementUI.Message({
+			// 	message:"账号已失效",
+			// 	type:"error"
+			// });
 		}
 		error.response.message = "账号已失效";
 		error.response.data.message = "账号已失效";

+ 20 - 1
src/services/requestConfig.js

@@ -5,10 +5,29 @@ var doubleClickList = []; //防连击的数组对象
 const endpoints = {
     upload: 'elab-marketing-system/behavior/brandMiniWeb/upload', //埋点接口
     login: 'elab-marketing-analyse/cockpit/login', //用户登录
+	// // webGL接口
+	getHouseTypeSpaceDetailsV2: 'elab-marketing-file/space_generation_background/getHouseTypeSpaceDetails/v2', //V1.1.0-城市首页
+	getHouseTypeSpaceDetails: 'elab-marketing-file/space_generation_background/getHouseTypeSpaceDetails', //V1.1.0-城市首页
+	
+	//    // 柔性定制接口
+	getHouseTypeSpaceWalls: '/elab-marketing-file/space_generation_background/getHouseTypeSpaceWalls', // 批量获取墙面信息
+	
+	houseDetail: 'elab-marketing-user/house/detail',
+	findHouseTypeSpaceList: 'elab-marketing-file/space_generation_background/findHouseTypeSpaceList',
+	layoutList: 'elab-marketing-content/aiDreamHouse/V3.0/layoutList',
+	labelList: 'elab-marketing-content/aiDreamHouse/V3.0/labelList',
+	findOverallArrangementList: 'elab-marketing-file/space_generation_background/findOverallArrangementList',
+	getOverallArrangementDetailsList: 'elab-marketing-file/space_generation_background/getOverallArrangementDetailsList',
+	choiceList: "elab-marketing-content/aiDreamHouse/V3.0/choiceList",
+	getHardboundEffects: "elab-marketing-file/space_vary/getHardboundEffects",
+	uploadImgControlNet: "elab-marketing-content/aiBeautyFamily/uploadImgControlNet",
+	// generateProcess: "elab-marketing-content/aiBeautyFamily/generateProcess",
+	getUploadToken: "elab-marketing-file/upload/getUploadToken",
+	findSpatialInfoList: "elab-marketing-file/flexible_customization/findSpatialInfoList",
 
 };
 window.requestConfig = async(endpoint, options, isHideLoading = false, preventDoubleClick = false, method = 'post') => {
-    if (!endpoints.hasOwnProperty(endpoint)) {
+	if (!endpoints.hasOwnProperty(endpoint)) {
         console.error(`no such endpoint: ${endpoint}`);
         return {
             message: "不存在该接口"

+ 141 - 0
src/static/layoutModelData.js

@@ -0,0 +1,141 @@
+var layoutModel = [
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_Mbed.glb', name: '1.5m床',modelName: 'BP_B_Mbed01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_smallcabinet.glb', name: '床头柜',modelName: 'BP_B_smallcabinet01', type:1},
+	// {url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_195M_C.gltf', name: '1.95m',modelName: 'BP_AutoWall_195M_C', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_bigbed.glb', name: '1.8m床',modelName: 'BP_B_bigbed01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_smallbed.glb', name: '1.2m床',modelName: 'BP_B_smallbed01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_verysmallbed.glb', name: '0.9m床',modelName: 'BP_B_verysmallbed', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_31sofa.gltf', name: '4人沙发',modelName: 'BP_L_31sofa01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_31TV.glb', name: '电视墙',modelName: 'BP_L_31TV01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_4people_square.gltf', name: '4人方桌',modelName: 'BP_D_4people_square', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_yigui.glb', name: '衣柜',modelName: 'BP_B_yigui01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_311sofa01.gltf', name: '5人沙发',modelName: 'BP_L_311sofa01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_321sofa.gltf', name: '6人沙发',modelName: 'BP_L_321sofa01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_2people_square.gltf', name: '2人方桌',modelName: 'BP_D_2people_square', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_6people_long.gltf', name: '6人长桌',modelName: 'BP_D_6people_long01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_6people_long.gltf', name: '6人长桌',modelName: 'BP_D_6people_long01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_8people_long.gltf', name: '8人长桌',modelName: 'BP_D_8people_long', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_12people_round1.gltf', name: '12人圆桌',modelName: 'BP_D_12people_round', type:1},
+	// {url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_penzai01.glb', name: '盆栽',modelName: 'BP_B_penzai02', type:1},
+
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_backsofa01.gltf', name: '靠背沙发01',modelName: 'BP_D_backsofa01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_facesofa01.gltf', name: '对坐沙发01',modelName: 'BP_D_facesofa01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_O_painting01.gltf', name: '挂画装饰',modelName: 'BP_DLBT_painting01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_painting01.glb', name: '挂画01',modelName: 'BP_B_painting01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_painting02.glb', name: '挂画02',modelName: 'BP_B_painting02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_bookshelf01.glb', name: '大书架01',modelName: 'BP_L_bookshelf01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_bookshelf02.glb', name: '大书架02',modelName: 'BP_L_bookshelf02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_dinetable01.gltf', name: '大展架01',modelName: 'BP_L_exhibition01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_Exhibition02.gltf', name: '大展架02',modelName: 'BP_L_exhibition02', type:1},
+	
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_exhibition04.gltf', name: '4m展架',modelName: 'BP_L_exhibition04', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_exhibition05.gltf', name: '5m展架',modelName: 'BP_L_exhibition05', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_exhibition06.gltf', name: '6m展架',modelName: 'BP_L_exhibition06', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_exhibition07.gltf', name: '7m展架',modelName: 'BP_L_exhibition07', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_3sofa01.glb', name: '3人沙发',modelName: 'BP_L_21sofa01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_facesofa02.gltf', name: '对坐沙发02',modelName: 'BP_D_facesofa02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_wardrobe01.glb', name: '1m衣柜',modelName: 'BP_B_wardrobe01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_wardrobe02.glb', name: '2m衣柜',modelName: 'BP_B_wardrobe02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_wardrobe03.glb', name: '3m衣柜',modelName: 'BP_B_wardrobe03', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_wardrobe04.glb', name: '4m衣柜',modelName: 'BP_B_wardrobe04', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_dresser01.glb', name: '梳妆台01',modelName: 'BP_B_dresser01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_bathtub01.glb', name: '浴缸01',modelName: 'BP_T_bathtub01', type:1},
+	
+	
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_table01.glb', name: '1m写字台',modelName: 'BP_B_table01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_stairs01.gltf', name: '楼梯01',modelName: 'BP_T_stairs01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_children01.gltf', name: '儿童家具01',modelName: 'BP_L_children01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_children02.gltf', name: '儿童家具02',modelName: 'BP_L_children02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_children03.gltf', name: '儿童家具03',modelName: 'BP_L_children03', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_2PeopleBasin01.glb', name: '2人台盆01',modelName: 'BP_T_2PeopleBasin01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_2PeopleBasin02.glb', name: '2人台盆02',modelName: 'BP_T_2PeopleBasin02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_flue001.glb', name: '烟道',modelName: 'BP_K_flue002', type:1},
+
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_cookerhood2.glb', name: '灶台',modelName: 'BP_K_cookerhood02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_icebox_2door001.glb', name: '冰箱',modelName: 'BP_K_icebox_2door002', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_shuipen01.glb', name: '水盆01',modelName: 'BP_K_shuipen01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_shuipen02.glb', name: '水盆02',modelName: 'BP_K_shuipen02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_Kitchentable001.glb', name: '台面',modelName: 'BP_K_Kitchentable002', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_2sofa.gltf', name: '2人沙发',modelName: 'BP_L_2sofa', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_caozuotai01.gltf', name: '操作台01',modelName: 'BP_K_caozuotai001', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_caozuotai02.glb', name: '操作台02',modelName: 'BP_K_caozuotai002', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_caozuotai03.glb', name: '操作台03',modelName: 'BP_K_caozuotai03', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_O_LightIndoorWall.gltf', name: '隔墙',modelName: 'BP_O_LightIndoorWall', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_TeaTable01.glb', name: '茶几01',modelName: 'BP_L_TeaRTable', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_children04.gltf', name: '儿童家具04',modelName: 'BP_L_children04', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_ReadingArea01.gltf', name: '阅读角01',modelName: 'BP_X_ReadingArea01', type:1},
+
+
+
+	
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_OpenShower01.glb', name: '开敞侧淋浴间',modelName: 'BP_T_OpenShower01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_matong.glb', name: '马桶',modelName: 'BP_T_matong', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_1PeopleBasin01.glb', name: '1人台盆01',modelName: 'BP_T_1PeopleBasin01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_flue001.glb', name: '水井管道01',modelName: 'BP_T_flue001', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_Locker01.glb', name: '储物柜01',modelName: 'BP_T_Locker01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_RelaxArea01.gltf', name: '休闲角01',modelName: 'BP_X_RelaxArea01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_RelaxArea02.gltf', name: '休闲角02',modelName: 'BP_X_RelaxArea02', type:1},
+
+
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_FlowerTerrace01_LongSide_0.3M.gltf', name: '长边花坛0.3M-长边位',modelName: 'BP_G_LongSide03M', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_FlowerTerrace_Corner_0.3M.gltf', name: '长边花坛0.3M-转角位',modelName: 'BP_G_Corner03M', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_FlowerTerrace_1.5M1.2M.gltf', name: '矩形花坛1.5M*1.2M',modelName: 'BP_G_1512M', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_FitnessArea01.gltf', name: '健身区',modelName: 'BP_G_FitnessArea01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_SunChairs01.gltf', name: '太阳椅',modelName: 'BP_G_SunChairs01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFrenchWindow_3.9M.gltf', name: '关闭落地窗-3.9M',modelName: 'BP_AutoWall_39M', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFrenchWindow_5.1M.gltf', name: '关闭落地窗-5.1M',modelName: 'BP_AutoWall_51M', type:1},
+
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFrenchWindow_6.3M.gltf', name: '关闭落地窗-6.3M',modelName: 'BP_AutoWall_63M', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFrenchWindow_6.9M.gltf', name: '关闭落地窗-6.9M',modelName: 'BP_AutoWall_69M', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_FoldingInternalDoor_1.95M.gltf', name: '户内折叠门',modelName: 'BP_AutoWall_195M', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_OpenInternalDoor_0.8M.glt', name: '关闭户内门-0.8M',modelName: 'BP_AutoWallr_08M', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tree00.glb', name: '大树',modelName: 'BP_G_tree00', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tree01.glb', name: '中树',modelName: 'BP_G_tree01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tree02.glb', name: '小树',modelName: 'BP_G_tree02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tree02.glb', name: '最小树',modelName: 'BP_G_tree03', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_parterre01.gltf', name: '9格花坛',modelName: 'BP_G_parterre01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_parterre03.gltf', name: '三角花坛',modelName: 'BP_G_parterre03', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_parterre04.gltf', name: '矩形花坛',modelName: 'BP_G_parterre04', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_parterre02.gltf', name: '内凹花坛',modelName: 'BP_G_parterre02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_parterre07.gltf', name: '双条花坛',modelName: 'BP_G_parterre07', type:1},
+
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_PartyTable01.gltf', name: '聚会长桌',modelName: 'BP_X_PartyTable01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_PoolTable01.gltf', name: '台球桌01',modelName: 'BP_X_PoolTable01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_weiqi01.gltf', name: '带伞棋坛',modelName: 'BP_G_weiqi01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_RelaxChair01_One.gltf', name: '单独休闲椅01',modelName: 'BP_X_RelaxChair01_One', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_RelaxChair02_One.gltf', name: '单独休闲椅02',modelName: 'BP_X_RelaxChair02_One', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_RelaxChair03_One.gltf', name: '单独休闲椅03',modelName: 'BP_X_RelaxChair03_One', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_swimmingpool01.gltf', name: '泳池01',modelName: 'BP_X_swimmingpool01', type:1},
+
+	
+	// {url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles01.gltf', name: '地砖01',modelName: 'BP_G_tiles01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles02.gltf', name: '地砖02',modelName: 'BP_G_tiles02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles03.gltf', name: '地砖03',modelName: 'BP_G_tiles03', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles04.gltf', name: '地砖04',modelName: 'BP_G_tiles04', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles05.gltf', name: '地砖05',modelName: 'BP_G_tiles05', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles06.gltf', name: '地砖06',modelName: 'BP_G_tiles06', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles07.gltf', name: '地砖07',modelName: 'BP_G_tiles07', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles08.gltf', name: '地砖08',modelName: 'BP_G_tiles08', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles09.gltf', name: '地砖09',modelName: 'BP_G_tiles09', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles10.gltf', name: '地砖10',modelName: 'BP_G_tiles10', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles11.gltf', name: '地砖11',modelName: 'BP_G_tiles11', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles12.gltf', name: '地砖12',modelName: 'BP_G_tiles12', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_G_tiles13.gltf', name: '地砖13',modelName: 'BP_G_tiles13', type:1},
+
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_OutdoorBar01.gltf', name: '户外酒吧台',modelName: 'BP_X_OutdoorBar01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_DinnerChair-red.glb', name: '单人餐椅01',modelName: 'BP_D_DinnerChair01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_LongDiningTable_240CM.glb', name: '2.4M长餐桌',modelName: 'BP_D_LongDiningTable_240CM', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_DiningDecration01.glb', name: '桌面饰品01',modelName: 'BP_D_DiningDecoration01_C', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_TeaTable02.glb', name: '茶几02',modelName: 'BP_L_TeaTable02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_TeaTable03.glb', name: '茶几03',modelName: 'BP_L_TeaTable03', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_carpet01.glb', name: '地毯01',modelName: 'BP_L_carpet01_C', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_2Sofa01.glb', name: '双人沙发',modelName: 'BP_L_2Sofa01_C', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_1Sofa01.glb', name: '单人沙发',modelName: 'BP_L_1Sofa01_C', type:1},
+	
+	
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_RelaxTable01.gltf', name: '单独休闲桌01',modelName: 'BP_X_RelaxTable01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_pillow01.glb', name: '枕头',modelName: 'BP_B_pillow01', type:1},
+	
+];
+
+module.exports = layoutModel;

+ 84 - 0
src/static/modelData.js

@@ -0,0 +1,84 @@
+
+var modelData = [
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_Mbed.gltf', name: '1.5m床',modelName: 'BP_B_Mbed01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_smallcabinet.gltf', name: '床头柜',modelName: 'BP_B_smallcabinet01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_bigbed.gltf', name: '1.8m床',modelName: 'BP_B_bigbed01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_bigbed.gltf', name: '1.2m床',modelName: 'BP_B_smallbed01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_31sofa.gltf', name: '4人沙发',modelName: 'BP_L_31sofa01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_31TV.gltf', name: '电视墙',modelName: 'BP_L_31TV01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_4people_square.gltf', name: '4人方桌',modelName: 'BP_D_4people_square', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_yigui.gltf', name: '衣柜',modelName: 'BP_B_yigui01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_311sofa01.gltf', name: '5人沙发',modelName: 'BP_L_311sofa01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_321sofa.gltf', name: '6人沙发',modelName: 'BP_L_321sofa01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_2people_square.gltf', name: '2人方桌',modelName: 'BP_D_2people_square', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_6people_long.gltf', name: '6人长桌',modelName: 'BP_D_6people_long01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_6people_long.gltf', name: '6人长桌',modelName: 'BP_D_6people_long01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_8people_long.gltf', name: '8人长桌',modelName: 'BP_D_8people_long', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_12people_round1.gltf', name: '12人圆桌',modelName: 'BP_D_12people_round', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_penzai01.gltf', name: '盆栽',modelName: 'BP_B_penzai02', type:1},
+	
+	
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_backsofa01.gltf', name: '靠背沙发01',modelName: 'BP_D_backsofa01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_facesofa01.gltf', name: '对坐沙发01',modelName: 'BP_D_facesofa01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_O_painting01.gltf', name: '挂画装饰',modelName: 'BP_DLBT_painting01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_bookshelf01.gltf', name: '大书架01',modelName: 'BP_L_bookshelf01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_bookshelf02.gltf', name: '大书架02',modelName: 'BP_L_bookshelf02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_dinetable01.gltf', name: '大展架01',modelName: 'BP_L_exhibition01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_D_dinetable01.gltf', name: '大展架02',modelName: 'BP_L_exhibition02', type:1},
+	
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_exhibition04.gltf', name: '4m展架',modelName: 'BP_L_exhibition04', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_exhibition05.gltf', name: '5m展架',modelName: 'BP_L_exhibition05', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_exhibition06.gltf', name: '6m展架',modelName: 'BP_L_exhibition06', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_exhibition07.gltf', name: '7m展架',modelName: 'BP_L_exhibition07', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_21sofa.gltf', name: '3人沙发',modelName: 'BP_L_21sofa01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_facesofa02.gltf', name: '对坐沙发02',modelName: 'BP_D_facesofa02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_wardrobe01.gltf', name: '1m衣柜',modelName: 'BP_B_wardrobe01', type:1},
+	
+	
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_wardrobe02.gltf', name: '2m衣柜',modelName: 'BP_B_wardrobe02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_wardrobe03.gltf', name: '3m衣柜',modelName: 'BP_B_wardrobe03', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_wardrobe04.gltf', name: '4m衣柜',modelName: 'BP_B_wardrobe04', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_dresser01.gltf', name: '梳妆台01',modelName: 'BP_B_dresser01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_bathtub01.gltf', name: '浴缸01',modelName: 'BP_T_bathtub01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_verysmallbed.gltf', name: '0.9m床',modelName: 'BP_B_verysmallbed', type:1},
+	
+	
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_B_table01.gltf', name: '1m写字台',modelName: 'BP_B_table01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_caozuotai03.gltf', name: '操作台03',modelName: 'BP_K_caozuotai03', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_stairs01.gltf', name: '楼梯01',modelName: 'BP_T_stairs01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_children01.gltf', name: '儿童家具01',modelName: 'BP_L_children01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_children02.gltf', name: '儿童家具02',modelName: 'BP_L_children02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_children03.gltf', name: '儿童家具03',modelName: 'BP_L_children03', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_2PeopleBasin01.gltf', name: '2人台盆01',modelName: 'BP_T_2PeopleBasin01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_2PeopleBasin02.gltf', name: '2人台盆03',modelName: 'BP_T_2PeopleBasin02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_flue001.gltf', name: '管井',modelName: 'BP_K_flue002', type:1},
+	
+	
+	
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_cookerhood2.gltf', name: '灶台',modelName: 'BP_K_cookerhood02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_icebox_2door001.gltf', name: '冰箱',modelName: 'BP_K_icebox_2door002', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_shuipen01.gltf', name: '水盆01',modelName: 'BP_K_shuipen01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_Kitchentable001.gltf', name: '台面',modelName: 'BP_K_Kitchentable002', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_2sofa.gltf', name: '2人沙发',modelName: 'BP_L_2sofa', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_caozuotai01.gltf', name: '操作台01',modelName: 'BP_K_caozuotai001', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_caozuotai02.gltf', name: '操作台02',modelName: 'BP_K_caozuotai002', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_O_LightIndoorWall.gltf', name: '隔墙',modelName: 'BP_O_LightIndoorWall', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_TeaTable01.gltf', name: '茶几01',modelName: 'BP_L_TeaRTable', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_L_children04.gltf', name: '儿童家具04',modelName: 'BP_L_children04', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_ReadingArea01.gltf', name: '阅读角01',modelName: 'BP_X_ReadingArea01', type:1},
+	
+	
+	
+	
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_OpenShower01.gltf', name: '开敞侧淋浴间',modelName: 'BP_T_OpenShower01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_matong.gltf', name: '马桶',modelName: 'BP_T_matong', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_1PeopleBasin01.gltf', name: '1人台盆01',modelName: 'BP_T_1PeopleBasin01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_flue001.gltf', name: '水井管道01',modelName: 'BP_T_flue001', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_T_Locker01.gltf', name: '储物柜01',modelName: 'BP_T_Locker01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_K_shuipen02.gltf', name: '水盆02',modelName: 'BP_K_shuipen02', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_RelaxArea01.gltf', name: '休闲角01',modelName: 'BP_X_RelaxArea01', type:1},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_X_RelaxArea02.gltf', name: '休闲角02',modelName: 'BP_X_RelaxArea02', type:1},
+	
+];
+
+module.exports = modelData;

+ 11 - 0
src/static/threex.js

@@ -0,0 +1,11 @@
+module.exports = {
+    getApp() {
+        return getApp()
+    },
+    getCurrentPages() {
+        return getCurrentPages()
+    },
+    wx_request() {
+        return wx.request
+    }
+}

+ 52 - 0
src/static/wallData.js

@@ -0,0 +1,52 @@
+
+// group :0 墙面 1 hu
+var wallType = [
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Standard.gltf', name: '承重墙',type:0, width:10, group:0, level:0, total:1},
+	{url: 'https://dm.static.elab-plus.com/3d/model/230519/qiangti.gltf', name: '实体墙面',type:3, width:10, group:0, level:0, total:0}, // 暂未使用
+
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_OpenInternalDoor_0.8M.gltf', name: '关闭户内门-0.8M',type:1, width:80, group:1, level:0, total:1},
+	// {url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_OpenInternalDoor_0.8M.gltf', name: '关闭户内门-1.2M',type:6, width:80, group:1, level:1, total:2},
+	
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedEntranceDoor_0.9M.gltf', name: '关闭入户门-0.9M',type:4, width:90, group:2, level:0, total:1},
+	
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFoldingWindow_0.6M.gltf', name: '关闭折叠窗-0.6M',type:2, width:60, group:3, level:0, total:5},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFoldingWindow_1.2M.gltf', name: '关闭折叠窗-1.2M',type:5, width:120, group:3, level:1, total:5},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFoldingWindow_2.4M.gltf', name: '关闭折叠窗-2.4M',type:8, width:240, group:3, level:2, total:5},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFoldingWindow_2.7M.gltf', name: '关闭折叠窗-2.7M',type:9, width:270, group:3, level:3, total:5},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFoldingWindow_3.6M.gltf', name: '关闭折叠窗-3.6M',type:10, width:360, group:3, level:4, total:5},
+
+	{url: 'https://dm.static.elab-plus.com/3d/model/20230606/langan/langan.gltf', name: '阳台栏杆',type:7, width:690, group:4, level:0, total:1},
+
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFrenchWindow_2.1M.gltf', name: '关闭落地窗-2.1M',type:11, width:210, group:5, level:0, total:8},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFrenchWindow_2.7M.gltf', name: '关闭落地窗-2.7M',type:12, width:270, group:5, level:1, total:8},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFrenchWindow_3.6M.gltf', name: '关闭落地窗-3.6M',type:13, width:360, group:5, level:2, total:8},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFrenchWindow_3.9M.gltf', name: '关闭落地窗-3.9M',type:14, width:390, group:5, level:3, total:8},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFrenchWindow_5.1M.gltf', name: '关闭落地窗-5.1M',type:15, width:480, group:5, level:4, total:8},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFrenchWindow_6.3M.gltf', name: '关闭落地窗-6.3M',type:16, width:630, group:5, level:5, total:8},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFrenchWindow_7.8M.gltf', name: '关闭落地窗-7.8M',type:17, width:780, group:5, level:6, total:8},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedFrenchWindow_8.7M.gltf', name: '关闭落地窗-8.7M',type:18, width:870, group:5, level:7, total:8},
+
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedLongWindow_0.9M.gltf', name: '关闭长条窗-0.9M',type:19, width:90, group:6, level:0, total:2},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_CLosedLongWindow_2.4M.gltf', name: '关闭长条窗-2.4M',type:20, width:240, group:6, level:1, total:2},
+
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Railing_1M.gltf', name: '扶手栏杆-1M',type:21, width:100, group:7, level:0, total:6},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Railing_2M.gltf', name: '扶手栏杆-2M',type:22, width:200, group:7, level:1, total:6},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Railing_3M.gltf', name: '扶手栏杆-3M',type:23, width:300, group:7, level:2, total:6},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Railing_4M.gltf', name: '扶手栏杆-4M',type:24, width:400, group:7, level:3, total:6},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Railing_5M.gltf', name: '扶手栏杆-5M',type:25, width:500, group:7, level:4, total:6},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Railing_6M.gltf', name: '扶手栏杆-6M',type:26, width:600, group:7, level:5, total:6},
+
+
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Standard.gltf', name: '实体墙面',type:27},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Standard.gltf', name: '实体墙面',type:28},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Standard.gltf', name: '实体墙面',type:29},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Standard.gltf', name: '实体墙面',type:30},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Standard.gltf', name: '实体墙面',type:31},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Standard.gltf', name: '实体墙面',type:32},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Standard.gltf', name: '实体墙面',type:33},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Standard.gltf', name: '实体墙面',type:34},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Standard.gltf', name: '实体墙面',type:35},
+	{url: 'https://dm.static.elab-plus.com/miniProgram/model/BP_AutoWall_Standard.gltf', name: '实体墙面',type:36},
+];
+
+module.exports = wallType;

BIN
webgl1/favicon.ico


Fichier diff supprimé car celui-ci est trop grand
+ 1 - 0
webgl1/index.html


Fichier diff supprimé car celui-ci est trop grand
+ 1 - 0
webgl1/static/css/app.cad3a579.css


Fichier diff supprimé car celui-ci est trop grand
+ 1 - 0
webgl1/static/css/chunk-vendors.911808b7.css


BIN
webgl1/static/fonts/element-icons.f1a45d74.ttf


BIN
webgl1/static/fonts/element-icons.ff18efd1.woff


BIN
webgl1/static/fonts/iconfont.962990fe.woff


BIN
webgl1/static/fonts/iconfont.96f2aa87.ttf


BIN
webgl1/static/fonts/iconfont.9e5bae0e.woff2


Fichier diff supprimé car celui-ci est trop grand
+ 1 - 0
webgl1/static/js/app.88c5ea02.js


Fichier diff supprimé car celui-ci est trop grand
+ 46 - 0
webgl1/static/js/chunk-vendors.f9210246.js