123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- // 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_WoodFloor1.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.glb", //模型地址
- 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;
- instancedMesh.setColorAt(i, child.material.color);
- instancedMesh.instanceColor.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);
- }
- });
- // this.pvCurPageName=="room_show"
- if(true){
- //给地板模型添加天花板
- 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.MeshStandardMaterial({
- color:0xffffff,
- metalness: 0.4, // 设置金属度为1.0
- roughness: 1 // 设置粗糙度为0.5
- });
- 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(),
- color:instancedMesh.material.color.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);//更新几何体的世界矩阵
- if(this.curSpaceObj.spaceId==cube.spaceId){//当前选中的空间才变化颜色
- instancedMesh.instanceColor.needsUpdate = true;//打开颜色修改开关,不开,颜色是不能修改额
- let color = new THREE.Color(0xFF9F40); // 使用sRGB颜色值
- // color.convertSRGBToLinear(); // 将颜色值转换为线性颜色值
- instancedMesh.setColorAt(instanced.instancedAtIndex, color);//修改这个几何体的颜色
- }
- });
- }).onComplete(()=>{//这个回调很可能会很慢
- this.tweenCameraAnmaChange(false);
- console.warn("***changeSpacesAnim-over***")
- if(this.curSpaceObj.spaceId==cube.spaceId){//当前选中的空间才恢复颜色
- cube.instancedMeshIndexList.forEach(instanced=>{
- let _index = instanced.instancedMeshIndex;//第一个geometry实例 在 全局Instance
- let instancedMesh = this.instancedSpaceMeshList[_index];//获取具体的网格实例
- let tmp = spaceInitMatrix.find(it=>it.index==_index);
- instancedMesh.instanceColor.needsUpdate = true;//打开颜色修改开关,不开,颜色是不能修改额
- instancedMesh.setColorAt(instanced.instancedAtIndex, tmp.color);//修改这个几何体的颜色
- });
- }
- });
- // 开始动画
- 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);
- }
- }
- }
|