loadModel.js 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194
  1. // const util = require('@/static/utils/util.js');
  2. const config = require('@/services/urlConfig.js');
  3. import modelData from '@/static/layoutModelData.js';
  4. import globlShowModel from '@/static/globlShowModel.js';
  5. // import requestConfig from '@/services/requestConfig.js';
  6. import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
  7. import * as THREE from 'three';
  8. // import { TWEEN } from '@/webgl/jsm/libs/tween.module.min.js';
  9. export default {
  10. data() {
  11. return {
  12. gltfLayouts: [],
  13. instancedFurList:[],
  14. // graderGltfLayouts: [],//花园地块的模型对象
  15. // graderInstancedFurList:[],//花园地块的模型
  16. arrFrunList:[],
  17. promise_list:[],
  18. dracoLoader:null,
  19. type:1,
  20. tmpList:[],
  21. realList:[],
  22. nextString:'_simple',//精简模型后缀
  23. // lastFrunList:[],
  24. }
  25. },
  26. watch: {},
  27. mounted() {
  28. console.warn("***loadmodel-mounted****")
  29. this.dracoLoader = new DRACOLoader();
  30. this.dracoLoader.setDecoderPath('./gltf/');
  31. this.dracoLoader.setDecoderConfig( { type: 'js' } );
  32. this.dracoLoader.preload();
  33. },
  34. methods: {
  35. // 设置空间数组的墙体信息
  36. async setSpaceListWallInfo(){
  37. for (let index = 0; index < this.spaceList.length; index++) {
  38. let spaceWallInfo = {wallN:false, wallS:false, wallW:false, wallE:false}
  39. const element = this.spaceList[index];
  40. const wallWIndex = this.gltfWalls.findIndex(item=>{
  41. return element.spaceId == item.spaceId && item.wallDirection == "W"
  42. })
  43. spaceWallInfo.wallW = wallWIndex == -1 ? false : true;
  44. const wallEIndex = this.gltfWalls.findIndex(item=>{
  45. return element.spaceId == item.spaceId && item.wallDirection == "E"
  46. })
  47. spaceWallInfo.wallE = wallEIndex == -1 ? false : true;
  48. const wallNIndex = this.gltfWalls.findIndex(item=>{
  49. return element.spaceId == item.spaceId && item.wallDirection == "N"
  50. })
  51. spaceWallInfo.wallN = wallNIndex == -1 ? false : true;
  52. const wallSIndex = this.gltfWalls.findIndex(item=>{
  53. return element.spaceId == item.spaceId && item.wallDirection == "S"
  54. })
  55. spaceWallInfo.wallS = wallSIndex == -1 ? false : true;
  56. element.spaceWallInfo = spaceWallInfo;
  57. }
  58. },
  59. // 批量获取空间模型信息
  60. async getOverallArrangementDetailsList(type=1) {
  61. // 设置空间数组的墙体信息
  62. // this.setSpaceListWallInfo();
  63. this.type = type;//加载类型,1空间加载 2 全局精简加载
  64. let arr = this.spaceList.map(it => it.layoutId).filter(it => it != 0);
  65. let parmas = {
  66. ids: arr,
  67. };
  68. // 默认的布局
  69. let res = await requestConfig("getOverallArrangementDetailsList", parmas);
  70. if (!res.success || !res.list || res.list.length == 0) {
  71. return false;
  72. }
  73. // let list1 = [];
  74. // let list2 = [];
  75. // res.list.forEach(singel=>{
  76. // let spaceType = this.spaceList.find(it => it.layoutId == signel.id).spaceType;
  77. // if(spaceType!=14){//花园地块
  78. // list1.push(singel);
  79. // }else{
  80. // list2.push(singel);
  81. // }
  82. // });
  83. this.promise_list = [];
  84. this.arrFrunList = res.list;
  85. this.gltfLayouts = []; //模型列表,所有空间里面的每个模型(家具)对应一条记录
  86. // 通过默认布局
  87. this.furnHandle(this.arrFrunList,[]);
  88. },
  89. //加载其他空间的家具模型
  90. loadLastSpaceModel(){
  91. if(!this.changeSpaces || this.changeSpaces.length==0){
  92. return false;
  93. }
  94. let spaceIds = this.changeSpaces.map(it=>it.spaceId);
  95. let layoutIds = this.spaceList.filter(item=>spaceIds.includes(item.spaceId)).map(it=>it.layoutId);
  96. let list = this.arrFrunList.filter(item=>{
  97. return !layoutIds.includes(item.id)
  98. })
  99. let spaceList = this.spaceList.filter(item=>{
  100. return !spaceIds.includes(item.spaceId)
  101. })
  102. // console.warn("***layoutIds***",layoutIds,spaceIds,this.gltfLayouts)
  103. this.furnHandle(list,spaceList)
  104. this.changeSpaces = []
  105. },
  106. //拆分家具模型加载逻辑
  107. furnHandle(arrFrunList, tmpSpaceList=[]){
  108. console.log("bug修复", arrFrunList, tmpSpaceList)
  109. if(!arrFrunList || arrFrunList.length == 0){
  110. return
  111. }
  112. let startTime = new Date().getTime();
  113. let tmpList = [];//临时数据
  114. let allowSpaceId = [this.curSpaceObj.spaceId];
  115. if(this.type == 2){//全局精简模型;需要的是所有空间的模型
  116. allowSpaceId = this.spaceList.map(it=>it.spaceId)
  117. }else{//空间模型模式
  118. allowSpaceId = [this.curSpaceObj.spaceId];
  119. if(this.curSpaceObj.spaceType==4){//厨房
  120. let list = this.spaceList.filter(it=>it.spaceType==2)
  121. allowSpaceId.push(...list.map(it=>it.spaceId));//客厅
  122. }
  123. if(this.curSpaceObj.spaceType==2){//餐厅
  124. let list = this.spaceList.filter(it=>it.spaceType==4)
  125. allowSpaceId.push(...list.map(it=>it.spaceId));//厨房
  126. }
  127. }
  128. console.warn("重新加载布局", arrFrunList,this.spaceList,this.gltfLayouts,allowSpaceId);
  129. arrFrunList.forEach(signel => {
  130. let spaceId = this.spaceList.find(it => it.layoutId == signel.id).spaceId;
  131. if(allowSpaceId.includes(spaceId)){//只加载允许的空间的布局,其他不加载
  132. let md = JSON.parse(signel.modelJson); //获取布局里面的模型信息
  133. //遍历模型信息,获取模型列表
  134. for (let i = 0; i < md.modelData.length; i++) {
  135. let item = md.modelData[i];
  136. item.spaceId = spaceId;
  137. item.layoutId = signel.id;
  138. item.h5Id = signel.id+""+item.id;//唯一标识
  139. if(item.modelName=='BP_furnitureBase_C'){
  140. // console.warn("***布局1***", item, signel.id)
  141. continue;
  142. }else{
  143. tmpList.push(item);
  144. // console.warn("***布局***", item, signel.id)
  145. }
  146. }
  147. }
  148. })
  149. // 处理删除模型时,其他空间引用了该模型时的重新载入处理
  150. // if(this.lastFrunList && this.lastFrunList.length>0){
  151. // let spaceIds = tmpSpaceList.map(it=>it.spaceId);
  152. // this.arrFrunList.forEach(signel => {
  153. // let spaceId = this.spaceList.find(it => it.layoutId == signel.id).spaceId;
  154. // let md = JSON.parse(signel.modelJson); //获取布局里面的模型信息
  155. // //遍历模型信息,获取模型列表
  156. // for (let i = 0; i < md.modelData.length; i++) {
  157. // let item = md.modelData[i];
  158. // if(this.lastFrunList.includes(item.modelName) && !spaceIds.includes(spaceId)){
  159. // item.spaceId = spaceId;
  160. // item.layoutId = signel.id;
  161. // item.h5Id = signel.id+""+item.id;//唯一标识
  162. // if(!tmpList.find(it=>it.h5Id==item.h5Id)){
  163. // // tmpList.push(item);
  164. // console.warn("***布局xxxx***", item, signel.id)
  165. // }
  166. // }
  167. // }
  168. // })
  169. // this.lastFrunList = [];
  170. // }
  171. this.tmpList = tmpList;
  172. if(this.type==2){//全局精简模型;需要的是所有空间的模型
  173. this.fliterList(tmpList);//精简模式下,只计算白名单里面的模型位置等信息
  174. console.warn("***fliterList***",this.realList.length);
  175. tmpList = this.realList;
  176. }
  177. let realFurArr = this.preFurnitureData(tmpList);//统一处理家具模型
  178. if(tmpSpaceList && tmpSpaceList.length>0){
  179. this.calculateLayoutModelSizeBySpace(tmpSpaceList) // 提前计算模型的位置
  180. }else{
  181. this.calculateLayoutModelSize() // 提前计算模型的位置
  182. }
  183. console.log("***realFurArr***", realFurArr,this.gltfLayouts);
  184. realFurArr && realFurArr.forEach((item,index) => {
  185. this.promise_list.push(
  186. new Promise((resolve, reject) => {
  187. this.loadLayoutModels(item, resolve);
  188. })
  189. )
  190. });
  191. Promise.all(this.promise_list).then(() => {
  192. let endTime = new Date().getTime();
  193. console.log("家具模型全部加载完成,时间:", endTime - startTime, this.gltfLayouts);
  194. this.loadLastSpaceModel();//加载剩余空间的家具模型
  195. })
  196. },
  197. //过滤掉不需要的家具
  198. fliterList(list){
  199. this.realList = [];
  200. let tempList = globlShowModel.map(it=>it.replace(this.nextString,''));
  201. //找到直接的家具模型
  202. list && list.forEach((mod)=>{
  203. let name = mod.modelName.substring(0,mod.modelName.length-2);
  204. if(tempList.includes(name)){
  205. this.realList.push(mod);
  206. }
  207. })
  208. this.realList.forEach((ref)=>{
  209. this.recursionFliter(ref)
  210. })
  211. },
  212. //递归处理不需要的家具
  213. recursionFliter(item){
  214. let _list = [];//
  215. if(parseInt(item.referenceModelBottom) > 0){
  216. _list.push(item.referenceModelBottom)
  217. }
  218. if(parseInt(item.referenceModelLeft) > 0){
  219. _list.push(item.referenceModelLeft)
  220. }
  221. if(parseInt(item.referenceModelRight) > 0){
  222. _list.push(item.referenceModelRight)
  223. }
  224. if(parseInt(item.referenceModelTop) > 0){
  225. _list.push(item.referenceModelTop)
  226. }
  227. if(_list.length==0){
  228. return false;
  229. }else{
  230. this.tmpList.forEach(tmp=>{
  231. if(_list.includes(tmp.id)){
  232. if(!this.realList.find(it=>it.h5Id==tmp.h5Id)){
  233. this.realList.push(tmp);
  234. this.recursionFliter(tmp);
  235. }
  236. }
  237. })
  238. }
  239. },
  240. //预处理需要加载墙体模型的数据-减少模型请求数
  241. preFurnitureData(list){
  242. let realFurnitureArr = [];//家具列表
  243. list && list.forEach((item, index) => {
  244. item.uniId = Date.now() + index;//唯一标识
  245. //获取墙体对应的gltb模型的相关信息
  246. let modelName = item.modelName;
  247. // console.log("布局模型名称", modelName);
  248. let layoutModel = modelData.find(it => modelName.indexOf(it.modelName) == 0); //模型地址
  249. // console.log("要加载的模型数据", item.modelName, layoutModel)
  250. if (layoutModel && layoutModel.url) {//该数据存在模型地址
  251. let object = realFurnitureArr.find(it=>it.url==layoutModel.url);
  252. //列表中还没有这个数据
  253. if(!object){
  254. let url = layoutModel.url;
  255. if(this.type==2){//全局精简模型;需要的是所有空间的模型
  256. //说明当前模型存在精简模型对象,则应该使用精简模型数据
  257. if(globlShowModel.includes(layoutModel.modelName + this.nextString)){
  258. let idx = layoutModel.url.lastIndexOf('.');
  259. url = url.substr(0,idx) + this.nextString + url.substr(idx)
  260. }
  261. }
  262. let it = {
  263. url:url,
  264. name:layoutModel.modelName,
  265. list:[item],
  266. }
  267. realFurnitureArr.push(it)
  268. }else{
  269. object.list.push(item);
  270. }
  271. let position = new THREE.Vector3();//当前几何体的位置参数
  272. let scale = new THREE.Vector3();//当前几何体的缩放参数
  273. let rotation = new THREE.Vector3();//当前几何体的缩放参数
  274. let md = {
  275. uniId:item.uniId,//家具模型实例的唯一标识
  276. spaceId:item.spaceId,
  277. id:item.id,
  278. userData:item,
  279. position:position,
  280. scale:scale,
  281. rotation:rotation,
  282. loaded:false,
  283. };
  284. this.gltfLayouts.push(md);
  285. }
  286. });
  287. return realFurnitureArr;
  288. },
  289. //加载家具模型-实例化方案
  290. loadLayoutModels(realData, resolve){
  291. var that = this;
  292. if(!realData.url){
  293. console.warn("***家具模型不存在***",realData);
  294. resolve();
  295. return false;
  296. }
  297. if(realData.name.includes('BP_XSPACE_deng_01')){//灯光
  298. resolve();
  299. }else{
  300. //不在白名单里面的,不加载
  301. if(!globlShowModel.includes(realData.name)){
  302. resolve();
  303. return false;
  304. }
  305. that.loader.setDRACOLoader(this.dracoLoader);
  306. that.loader.load(realData.url, ( gltf ) => {
  307. gltf.scene.traverse((child)=> {
  308. if (child.isMesh && child.visible) {
  309. let instancedMesh = new THREE.InstancedMesh(child.geometry.clone(), child.material.clone(), realData.list.length);
  310. this.instancedFurList.push(instancedMesh);
  311. //realData 该模型被重复使用时的每一次的形变参数等
  312. realData.list && realData.list.forEach((it,i)=>{
  313. let gltfFurn = that.gltfLayouts.find(itme=>itme.uniId==it.uniId);//判断是否已经添加过
  314. gltf.scene.rotation.y = gltfFurn.rotation.y;
  315. gltf.scene.position.set(gltfFurn.position.x,0,gltfFurn.position.z);
  316. gltf.scene.scale.set(gltfFurn.scale.x,1,gltfFurn.scale.z);
  317. gltf.scene.updateMatrixWorld();//更新世界坐标-这样,子模型也同步更新了
  318. instancedMesh.setMatrixAt(i, child.matrixWorld);
  319. instancedMesh.instanceMatrix.needsUpdate = true;
  320. gltfFurn.loaded = true;
  321. if(!gltfFurn.instancedMeshIndexList){//标识网格实例数组的序号 以及 当前几何体 在网格实例的序号
  322. gltfFurn.instancedMeshIndexList = [
  323. {instancedMeshIndex:this.instancedFurList.length-1,instancedAtIndex:i},
  324. ]
  325. }else{
  326. gltfFurn.instancedMeshIndexList.push({
  327. instancedMeshIndex:this.instancedFurList.length-1,instancedAtIndex:i
  328. })
  329. }
  330. })
  331. instancedMesh.userType = "layoutMesh";
  332. if(realData.name.includes("BP_L_carpet01")){//地毯接收阴影
  333. instancedMesh.receiveShadow = true;//对象是否接收阴影
  334. }else{
  335. instancedMesh.castShadow = true;//对象是否产生阴影
  336. }
  337. this.scene.add(instancedMesh);//添加到场景中
  338. }
  339. });
  340. resolve();
  341. });
  342. }
  343. },
  344. //加载模型
  345. loadLayoutModelsOld(modelObj, resolve) {
  346. let that = this;
  347. const modelName = modelObj.modelName;
  348. console.log("布局模型名称", modelName);
  349. let layoutModel = modelData.find(it => modelName.indexOf(it.modelName) == 0); //模型地址
  350. if (!layoutModel || !layoutModel.url) {
  351. resolve();
  352. return false
  353. }
  354. let url = layoutModel.url;
  355. console.log("布局模型数据", layoutModel);
  356. that.loader.load(url, (gltf) => {
  357. // console.log("布局模型加载成功", gltf);
  358. let model = gltf.scene; // 获取模型
  359. model.name = layoutModel.modelName;
  360. model.userType = "layoutMesh";
  361. model.userData = modelObj;
  362. // model.rotation.y = Math.PI / 2 ; // 旋转 90 度
  363. this.gltfLayouts.push(model);
  364. resolve();
  365. });
  366. },
  367. //清除当前楼层下的所有家具模型
  368. clearAllLayoutData(){
  369. let deleList = this.scene && this.scene.children.filter(object=>{
  370. if(object.userType=="layoutMesh"){
  371. return object
  372. }
  373. })
  374. // console.warn("***deleList***",deleList)
  375. if(deleList && deleList.length>0){
  376. this.scene.remove(...deleList);
  377. }
  378. this.gltfLayouts = [];
  379. this.instancedFurList = [];
  380. },
  381. // 切换家具的显示隐藏
  382. changeLayoutModelState(isShow=false){
  383. if(isShow){
  384. this.instancedFurList.forEach(it=>{
  385. if(it){
  386. it.visible = isShow;
  387. }
  388. })
  389. console.log("移动过程中显示隐藏空间家具", this.gltfLayouts,isShow,this.changeSpaces)
  390. return false;
  391. }
  392. const changeSpaceList = this.leftSpaces.concat(this.rightSpaces); // 只改变空间尺寸变化的家具模型
  393. console.log("移动过程中显示隐藏空间家具", this.gltfLayouts,isShow, this.leftSpaces, this.rightSpaces,this.changeSpaces);
  394. for (let index = 0; index < changeSpaceList.length; index++) {
  395. let element = changeSpaceList[index];
  396. let gltfLayoutModels = this.gltfLayouts.filter(item => {
  397. return element.layoutId == item.userData.layoutId && element.spaceId == item.userData.spaceId;
  398. })
  399. if (!gltfLayoutModels || gltfLayoutModels.length == 0) {
  400. continue;
  401. }
  402. console.warn("***隐藏空间家具***",element,gltfLayoutModels)
  403. for (let j = 0; j < gltfLayoutModels.length; j++) {
  404. let cube = gltfLayoutModels[j];
  405. this.changeCubeState(cube, isShow);
  406. }
  407. }
  408. },
  409. // 显示隐藏指定cube的状态
  410. changeCubeState(cube, isShow){
  411. let lay = this.gltfLayouts.find(it=>it.uniId==cube.uniId);
  412. if(cube.instancedMeshIndexList && cube.instancedMeshIndexList.length>0){
  413. cube.instancedMeshIndexList.forEach(item=>{
  414. let index = item.instancedMeshIndex;
  415. let instancedMesh = this.instancedFurList[index];//网格实例对象
  416. // let curMeshIndex = item.instancedAtIndex;//当前家具模型在网格实例对象里面的序号
  417. // let stratMatrix = new THREE.Matrix4();//定义一个四维矩阵
  418. // instancedMesh.getMatrixAt(curMeshIndex,stratMatrix);//获取当前几何体的四维矩阵到stratMatrix里面
  419. // instancedMesh.instanceMatrix.needsUpdate = true;//更新之前,必须开启开关
  420. instancedMesh.visible = isShow;
  421. // instancedMesh.setMatrixAt(curMeshIndex,stratMatrix);//更新几何体的世界矩阵
  422. })
  423. }
  424. },
  425. // 删除对应空间家具模型
  426. deleteLayoutModel(spaceObj, layoutObj){
  427. const oldLayoutIndex = this.arrFrunList.findIndex((item)=>{
  428. return item.id == spaceObj.layoutId
  429. })
  430. //对应空间的布局替换为新的布局数据
  431. if(oldLayoutIndex!=-1 && layoutObj){
  432. this.arrFrunList[oldLayoutIndex] = layoutObj
  433. // this.arrFrunList.splice(oldLayoutIndex,1)
  434. }
  435. if(!layoutObj){//当前空间不存在布局了
  436. this.arrFrunList.splice(oldLayoutIndex,1)
  437. spaceObj.layoutId = null;//为了确保传递到下一页的空间里面也没有布局信息,确保布局一致
  438. }
  439. console.log("准备删除模型", spaceObj,oldLayoutIndex, this.gltfLayouts);
  440. //寻找当前空间下的所有家具模型对象
  441. const gltfLayoutModels = this.gltfLayouts.filter(item => {
  442. return spaceObj.layoutId == item.userData.layoutId && spaceObj.spaceId == item.userData.spaceId;
  443. })
  444. //不存在则不处理
  445. if (!gltfLayoutModels || gltfLayoutModels.length == 0) {
  446. return;
  447. }
  448. let deleList = []
  449. for (let j = 0; j < gltfLayoutModels.length; j++) {
  450. const cube = gltfLayoutModels[j];
  451. this.gltfLayouts.splice(this.gltfLayouts.findIndex(it=>it.uniId==cube.uniId),1);//删除gltfLayouts里面的数据
  452. if(cube.instancedMeshIndexList && cube.instancedMeshIndexList.length>0){
  453. cube.instancedMeshIndexList.forEach(item=>{
  454. let index = item.instancedMeshIndex;
  455. let instancedMesh = this.instancedFurList[index];//网格实例对象
  456. if(instancedMesh){
  457. instancedMesh.dispose();
  458. deleList.push(instancedMesh);//等待释放资源
  459. this.instancedFurList[index] = null;
  460. // if(instancedMesh.count>1){//表示其他空间还存在这个模型,应该重新加入计算中
  461. // if(!this.lastFrunList.includes(cube.userData.modelName)){
  462. // this.lastFrunList.push(cube.userData.modelName);
  463. // }
  464. // }
  465. }
  466. })
  467. }
  468. }
  469. this.scene.remove(...deleList);//释放家具的资源,this.instancedFurList
  470. console.log("删除模型了", spaceObj, this.gltfLayouts);
  471. },
  472. // 计算家具的位置
  473. calculateLayoutModelSize() {
  474. console.log("计算家具的位置", this.gltfLayouts,this.changeSpaces);
  475. // 有改变空间,只刷新改变空间的模型数据
  476. const spaceList = (!this.changeSpaces || this.changeSpaces.length ==0) ? this.spaceList : this.changeSpaces;
  477. for (let index = 0; index < spaceList.length; index++) {
  478. const element = spaceList[index];
  479. const gltfLayoutModels = this.gltfLayouts.filter(item => {
  480. return element.layoutId == item.userData.layoutId && element.spaceId == item.userData.spaceId;
  481. })
  482. //空间下不存在家具模型,则该空间不需要进行下一步处理
  483. if (!gltfLayoutModels || gltfLayoutModels.length == 0) {
  484. continue;
  485. }
  486. gltfLayoutModels.sort(function(a, b) {
  487. return a.userData.level - b.userData.level
  488. });
  489. // console.log("对应空间ID的模型数组", this.gltfLayouts, element.spaceId, gltfLayoutModels)
  490. for (let j = 0; j < gltfLayoutModels.length; j++) {
  491. const cube = gltfLayoutModels[j];
  492. this.drawLayoutModel(element, cube);
  493. }
  494. }
  495. },
  496. // 计算家具的位置
  497. calculateLayoutModelSizeBySpace(spaceList) {
  498. for (let index = 0; index < spaceList.length; index++) {
  499. const element = spaceList[index];
  500. const gltfLayoutModels = this.gltfLayouts.filter(item => {
  501. return element.layoutId == item.userData.layoutId && element.spaceId == item.userData.spaceId;
  502. })
  503. // console.log("计算指定空间的家具的位置", element, element.layoutId, gltfLayoutModels);
  504. //空间下不存在家具模型,则该空间不需要进行下一步处理
  505. if (!gltfLayoutModels || gltfLayoutModels.length == 0) {
  506. continue;
  507. }
  508. gltfLayoutModels.sort(function(a, b) {
  509. return a.userData.level - b.userData.level
  510. });
  511. // console.log("对应空间ID的模型数组", this.gltfLayouts, element.spaceId, gltfLayoutModels)
  512. for (let j = 0; j < gltfLayoutModels.length; j++) {
  513. const cube = gltfLayoutModels[j];
  514. this.drawLayoutModel(element, cube);
  515. }
  516. }
  517. },
  518. // 绘制模型
  519. drawLayoutModel(curSpace, cube) {
  520. const {
  521. centerX,
  522. spaceId
  523. } = curSpace;
  524. const cubeInfo = this.resetModelParameters(curSpace, cube.userData);
  525. // const cubeInfo = cube.userData;
  526. let centerY = curSpace.centerY * -1; // UE和ThreeJS坐标做相反
  527. // 默认空间中心点
  528. let positionX = centerX;
  529. let positionY = centerY;
  530. let rotationY = Math.PI / 2;
  531. let scaleX = 1;
  532. let scaleY = 1;
  533. // 空间尺寸
  534. let spaceWidth = curSpace.spaceWidth;
  535. let spaceHeight = curSpace.spaceHeight;
  536. // 模型尺寸
  537. let modelWidth = cubeInfo.modelWidth;
  538. let modelHeight = cubeInfo.modelHeight;
  539. // 判断旋转
  540. if (parseFloat(cubeInfo.rotation) == 90) {
  541. rotationY = 0;
  542. // 交换尺寸
  543. // modelWidth = cubeInfo.modelHeight;
  544. // modelHeight = cubeInfo.modelWidth;
  545. }
  546. if (parseFloat(cubeInfo.rotation) == 180) {
  547. rotationY = -Math.PI / 2;
  548. // modelWidth = cubeInfo.modelHeight;
  549. // modelHeight = cubeInfo.modelWidth;
  550. }
  551. if (parseFloat(cubeInfo.rotation) == -90) {
  552. rotationY = -Math.PI;
  553. // 交换尺寸
  554. // modelWidth = cubeInfo.modelHeight;
  555. // modelHeight = cubeInfo.modelWidth;
  556. }
  557. // 判断靠墙
  558. if (cubeInfo.isStepAsideLeft == 'true') {
  559. positionX = centerX - (spaceWidth / 2 - modelWidth / 2);
  560. if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
  561. positionX = centerX - (spaceWidth / 2 - modelWidth / 2);
  562. }
  563. positionX += parseFloat(cubeInfo.marginLeft);
  564. positionX += curSpace.spaceWallInfo.wallW ? 10 : 0;
  565. }
  566. if (cubeInfo.isStepAsideRight == 'true') {
  567. positionX = centerX + (spaceWidth / 2 - modelWidth / 2);
  568. if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
  569. positionX = centerX + (spaceWidth / 2 - modelWidth / 2);
  570. }
  571. positionX -= parseFloat(cubeInfo.marginRight);
  572. positionX -= curSpace.spaceWallInfo.wallE ? 10 : 0;
  573. }
  574. if (cubeInfo.isStepAsideTop == 'true') {
  575. positionY = centerY - (spaceHeight / 2 - modelHeight / 2);
  576. if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
  577. positionY = centerY - (spaceHeight / 2 - modelHeight / 2);
  578. }
  579. positionY += parseFloat(cubeInfo.marginTop);
  580. positionY += curSpace.spaceWallInfo.wallN ? 10 : 0;
  581. }
  582. if (cubeInfo.isStepAsideBottom == 'true') {
  583. positionY = centerY + (spaceHeight / 2 - modelHeight / 2);
  584. if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
  585. positionY = centerY + (spaceHeight / 2 - modelHeight / 2);
  586. }
  587. positionY -= parseFloat(cubeInfo.marginBottom);
  588. positionY -= curSpace.spaceWallInfo.wallS ? 10 : 0;
  589. }
  590. // 参照物
  591. if (parseInt(cubeInfo.referenceModelTop) > 0) {
  592. const referenceModel = this.gltfLayouts.find(item => {
  593. const layoutModelData = item.userData;
  594. return layoutModelData.id == parseInt(cubeInfo.referenceModelTop) && layoutModelData
  595. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  596. })
  597. if(!referenceModel){
  598. console.warn("***no-data***",cubeInfo.referenceModelTop,cubeInfo)
  599. return false
  600. }
  601. positionY = referenceModel.position.z * 100 + (referenceModel.userData.modelHeight / 2 + cubeInfo
  602. .modelHeight / 2);
  603. positionY = positionY + parseFloat(cubeInfo.marginTop);
  604. }
  605. if (parseInt(cubeInfo.referenceModelBottom) > 0) {
  606. const referenceModel = this.gltfLayouts.find(item => {
  607. const layoutModelData = item.userData;
  608. return layoutModelData.id == parseInt(cubeInfo.referenceModelBottom) && layoutModelData
  609. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  610. })
  611. if(!referenceModel){
  612. console.warn("***no-data***",cubeInfo.referenceModelBottom,cubeInfo)
  613. return false
  614. }
  615. positionY = referenceModel.position.z * 100 - (referenceModel.userData.modelHeight / 2 + cubeInfo
  616. .modelHeight / 2);
  617. positionY = positionY - parseFloat(cubeInfo.marginBottom);
  618. }
  619. if (parseInt(cubeInfo.referenceModelLeft) > 0) {
  620. const referenceModel = this.gltfLayouts.find(item => {
  621. const layoutModelData = item.userData;
  622. return layoutModelData.id == parseInt(cubeInfo.referenceModelLeft) && layoutModelData
  623. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  624. })
  625. if(!referenceModel){
  626. console.warn("***no-data***",cubeInfo.referenceModelLeft,cubeInfo)
  627. return false
  628. }
  629. positionX = referenceModel.position.x * 100 + (referenceModel.userData.modelWidth / 2 + cubeInfo
  630. .modelWidth / 2);
  631. positionX = positionX + parseFloat(cubeInfo.marginLeft);
  632. }
  633. if (parseInt(cubeInfo.referenceModelRight) > 0) {
  634. const referenceModel = this.gltfLayouts.find(item => {
  635. const layoutModelData = item.userData;
  636. return layoutModelData.id == parseInt(cubeInfo.referenceModelRight) && layoutModelData
  637. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  638. })
  639. if(!referenceModel){
  640. console.warn("***no-data***",cubeInfo.referenceModelRight,cubeInfo)
  641. return false
  642. }
  643. positionX = referenceModel.position.x * 100 - (referenceModel.userData.modelWidth / 2 + cubeInfo
  644. .modelWidth / 2);
  645. positionX = positionX - parseFloat(cubeInfo.marginRight);
  646. }
  647. if (cubeInfo.isFixedWidth == "false" || cubeInfo.isFixedHeight == "false") { // 固定尺寸
  648. // 靠墙拉伸
  649. if (cubeInfo.isStepAsideTop == 'true' && cubeInfo.isStepAsideBottom == 'true') {
  650. // console.log("高度拉伸", spaceHeight / modelHeight)
  651. positionY = centerY;
  652. if (curSpace.spaceWallInfo.wallN && curSpace.spaceWallInfo.wallS) {
  653. spaceHeight -= 20 + parseFloat(cubeInfo.marginTop) + parseFloat(cubeInfo.marginBottom);
  654. positionY += parseFloat(cubeInfo.marginTop) / 2 ;
  655. positionY -= parseFloat(cubeInfo.marginBottom) / 2;
  656. } else if (curSpace.spaceWallInfo.wallN) {
  657. spaceHeight -= 10 + parseFloat(cubeInfo.marginTop) + parseFloat(cubeInfo.marginBottom);
  658. positionY += 10 / 2;
  659. positionY += parseFloat(cubeInfo.marginTop) / 2;
  660. positionY -= parseFloat(cubeInfo.marginBottom) / 2;
  661. } else if (curSpace.spaceWallInfo.wallS) {
  662. spaceHeight -= 10 + parseFloat(cubeInfo.marginTop) + parseFloat(cubeInfo.marginBottom);
  663. positionY -= 10 / 2;
  664. positionY += parseFloat(cubeInfo.marginTop) / 2 ;
  665. positionY -= parseFloat(cubeInfo.marginBottom) / 2;
  666. }else {
  667. spaceHeight -= parseFloat(cubeInfo.marginTop) + parseFloat(cubeInfo.marginBottom);
  668. positionY += parseFloat(cubeInfo.marginTop) / 2 ;
  669. positionY -= parseFloat(cubeInfo.marginBottom) / 2;
  670. }
  671. // 计算缩放
  672. if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
  673. scaleY = spaceHeight / modelHeight;
  674. } else {
  675. scaleX = spaceHeight / modelHeight;
  676. }
  677. }
  678. if (cubeInfo.isStepAsideLeft == 'true' && cubeInfo.isStepAsideRight == 'true') {
  679. // console.log("宽度拉伸11111", spaceWidth / modelWidth)
  680. positionX = centerX;
  681. if (curSpace.spaceWallInfo.wallW && curSpace.spaceWallInfo.wallE) {
  682. spaceWidth -= 20 + parseFloat(cubeInfo.marginLeft) + parseFloat(cubeInfo.marginRight);
  683. positionX += parseFloat(cubeInfo.marginLeft) / 2;
  684. positionX -= parseFloat(cubeInfo.marginRight) / 2;
  685. } else if (curSpace.spaceWallInfo.wallW) {
  686. spaceWidth -= 10 + parseFloat(cubeInfo.marginLeft) + parseFloat(cubeInfo.marginRight);
  687. positionX += 10 / 2;
  688. positionX += parseFloat(cubeInfo.marginLeft) / 2;
  689. positionX -= parseFloat(cubeInfo.marginRight) / 2;
  690. } else if (curSpace.spaceWallInfo.wallE) {
  691. spaceWidth -= 10 + parseFloat(cubeInfo.marginLeft) + parseFloat(cubeInfo.marginRight);
  692. positionX -= 10 / 2;
  693. positionX += parseFloat(cubeInfo.marginLeft) / 2;
  694. positionX -= parseFloat(cubeInfo.marginRight) / 2;
  695. }else {
  696. spaceWidth -= parseFloat(cubeInfo.marginLeft) + parseFloat(cubeInfo.marginRight);
  697. positionX += parseFloat(cubeInfo.marginLeft) / 2;
  698. positionX -= parseFloat(cubeInfo.marginRight) / 2;
  699. }
  700. // console.log("模型计算位置" , parseFloat(cubeInfo.rotation))
  701. // 计算缩放
  702. if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
  703. scaleX = spaceWidth / modelWidth;
  704. } else {
  705. scaleY = spaceWidth / modelWidth;
  706. }
  707. }
  708. // 单个参照物和墙面拉伸
  709. if (cubeInfo.isStepAsideTop == 'true' && parseInt(cubeInfo.referenceModelBottom) > 0) {
  710. const referenceModel = this.gltfLayouts.find(item => {
  711. const layoutModelData = item.userData;
  712. return layoutModelData.id == parseInt(cubeInfo.referenceModelBottom) && layoutModelData
  713. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  714. })
  715. const referenceModelPositionY = referenceModel.position.z * 100 - referenceModel.userData
  716. .modelHeight / 2 - parseFloat(cubeInfo.marginBottom);
  717. const wallPositionY = centerY - spaceHeight / 2 + (curSpace.spaceWallInfo.wallN ? 10 : 0) +
  718. parseFloat(cubeInfo.marginTop);
  719. const newModelHeight = Math.abs(referenceModelPositionY - wallPositionY);
  720. // console.log("上边拉伸", referenceModelPositionY, wallPositionY, newModelHeight)
  721. if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
  722. scaleY = newModelHeight / modelHeight;
  723. } else {
  724. scaleX = newModelHeight / modelHeight;
  725. }
  726. positionY = wallPositionY + newModelHeight / 2;
  727. }
  728. if (cubeInfo.isStepAsideBottom == 'true' && parseInt(cubeInfo.referenceModelTop) > 0) {
  729. const referenceModel = this.gltfLayouts.find(item => {
  730. const layoutModelData = item.userData;
  731. return layoutModelData.id == parseInt(cubeInfo.referenceModelTop) && layoutModelData
  732. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  733. })
  734. const referenceModelPositionY = referenceModel.position.z * 100 + referenceModel.userData
  735. .modelHeight / 2 + parseFloat(cubeInfo.marginTop) + (curSpace.spaceWallInfo.wallN ? 10 : 0);
  736. const wallPositionY = centerY + spaceHeight / 2 - (curSpace.spaceWallInfo.wallS ? 10 : 0) -
  737. parseFloat(cubeInfo.marginBottom);
  738. const newModelHeight = Math.abs(referenceModelPositionY - wallPositionY);
  739. if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
  740. scaleY = newModelHeight / modelHeight;
  741. } else {
  742. scaleX = newModelHeight / modelHeight;
  743. }
  744. positionY = wallPositionY - newModelHeight / 2;
  745. }
  746. if (cubeInfo.isStepAsideLeft == 'true' && parseInt(cubeInfo.referenceModelRight) > 0) {
  747. // console.log("左边拉伸")
  748. const referenceModel = this.gltfLayouts.find(item => {
  749. const layoutModelData = item.userData;
  750. return layoutModelData.id == parseInt(cubeInfo.referenceModelRight) && layoutModelData
  751. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  752. })
  753. const referenceModelPositionX = referenceModel.position.x * 100 - referenceModel.userData
  754. .modelWidth / 2 - parseFloat(cubeInfo.marginLeft);
  755. const wallPositionX = centerX - spaceWidth / 2 + (curSpace.spaceWallInfo.wallE ? 10 : 0) +
  756. parseFloat(cubeInfo.marginRight);
  757. const newModelWidth = Math.abs(referenceModelPositionX - wallPositionX);
  758. if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
  759. scaleX = newModelWidth / modelWidth;
  760. } else {
  761. scaleY = newModelWidth / modelWidth;
  762. }
  763. positionX = wallPositionX + newModelWidth / 2;
  764. }
  765. if (cubeInfo.isStepAsideRight == 'true' && parseInt(cubeInfo.referenceModelLeft) > 0) {
  766. const referenceModel = this.gltfLayouts.find(item => {
  767. const layoutModelData = item.userData;
  768. return layoutModelData.id == parseInt(cubeInfo.referenceModelLeft) && layoutModelData
  769. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  770. })
  771. const referenceModelPositionX = referenceModel.position.x * 100 + referenceModel.userData
  772. .modelWidth / 2 + parseFloat(cubeInfo.marginLeft);
  773. const wallPositionX = centerX + spaceWidth / 2 - (curSpace.spaceWallInfo.wallE ? 10 : 0) -
  774. parseFloat(cubeInfo.marginRight);
  775. const newModelWidth = Math.abs(referenceModelPositionX - wallPositionX);
  776. if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
  777. scaleX = newModelWidth / modelWidth;
  778. } else {
  779. scaleY = newModelWidth / modelWidth;
  780. }
  781. positionX = wallPositionX - newModelWidth / 2;
  782. // console.log("右边拉伸", Math.abs(parseFloat(cubeInfo.rotation)))
  783. }
  784. if(parseInt(cubeInfo.referenceModelBottom) > 0 && parseInt(cubeInfo.referenceModelTop) > 0){
  785. // 上边惨遭物
  786. const referenceModelTop = this.gltfLayouts.find(item => {
  787. const layoutModelData = item.userData;
  788. return layoutModelData.id == parseInt(cubeInfo.referenceModelTop) && layoutModelData
  789. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  790. })
  791. // 下边参照物
  792. const referenceModelBottom = this.gltfLayouts.find(item => {
  793. const layoutModelData = item.userData;
  794. return layoutModelData.id == parseInt(cubeInfo.referenceModelBottom) && layoutModelData
  795. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  796. })
  797. const referenceModelTopPositionY = referenceModelTop.position.z * 100 + referenceModelTop.userData
  798. .modelHeight / 2 + parseFloat(cubeInfo.marginTop);
  799. const referenceModelBottomPositionY = referenceModelBottom.position.z * 100 - referenceModelBottom.userData
  800. .modelHeight / 2 - parseFloat(cubeInfo.marginBottom);
  801. const newModelHeight = Math.abs(referenceModelTopPositionY - referenceModelBottomPositionY);
  802. if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
  803. scaleY = newModelHeight / modelHeight;
  804. } else {
  805. scaleX = newModelHeight / modelHeight;
  806. }
  807. positionY = referenceModelBottomPositionY - newModelHeight / 2;
  808. }
  809. if(parseInt(cubeInfo.referenceModelLeft) > 0 && parseInt(cubeInfo.referenceModelRight) > 0){
  810. const referenceModelLeft = this.gltfLayouts.find(item => {
  811. const layoutModelData = item.userData;
  812. return layoutModelData.id == parseInt(cubeInfo.referenceModelLeft) && layoutModelData
  813. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  814. })
  815. const referenceModelRight = this.gltfLayouts.find(item => {
  816. const layoutModelData = item.userData;
  817. return layoutModelData.id == parseInt(cubeInfo.referenceModelRight) && layoutModelData
  818. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  819. })
  820. const referenceModelLeftPositionX = referenceModelLeft.position.x * 100 + referenceModelLeft.userData
  821. .modelWidth / 2 + parseFloat(cubeInfo.marginLeft);
  822. const referenceModelRightPositionX = referenceModelRight.position.x * 100 - referenceModelRight.userData
  823. .modelWidth / 2 - parseFloat(cubeInfo.marginRight);
  824. const newModelWidth = Math.abs(referenceModelLeftPositionX - referenceModelRightPositionX);
  825. if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
  826. scaleX = newModelWidth / modelWidth;
  827. } else {
  828. scaleY = newModelWidth / modelWidth;
  829. }
  830. positionX = referenceModelRightPositionX - newModelWidth / 2;
  831. }
  832. }
  833. // console.log("模型计算位置--", positionX, positionY)
  834. // console.log("模型计算位置", cubeInfo, centerX, centerY, spaceWidth, spaceHeight, modelWidth, modelHeight, spaceId, scaleX, scaleY, positionX, positionY, cubeInfo.modelName)
  835. let oldPosition = new THREE.Vector3();//当前几何体的位置参数
  836. oldPosition.copy(cube.position);
  837. cube.position.x = positionX / 100;
  838. cube.position.z = positionY / 100;
  839. cube.rotation.y = rotationY;
  840. cube.scale.x = scaleX;
  841. cube.scale.z = scaleY;
  842. cube.scale.y = 1;
  843. // if (!cube.parent) { //说明还没添加到场景中-旧版方法
  844. // this.scene.add(cube); //处理完毕后在加入场景中
  845. // }
  846. // if(scaleX>1 || scaleY>1){
  847. // console.warn("***scaleinfo***",cubeInfo.id,scaleX,scaleY,cubeInfo.modelName)
  848. // }
  849. if(this.type==2){//全局精简加载
  850. let name = cubeInfo.modelName.substring(0, cubeInfo.modelName.length - 2);
  851. if(globlShowModel.includes(name)){
  852. if(cubeInfo.modelName=='BP_XSPACE_deng_01_C'){//灯光
  853. this.lightHandle(cube)
  854. }else{
  855. this.updateInfo(cube,oldPosition,scaleX,scaleY);//实例化方法
  856. }
  857. }
  858. }else{
  859. if(cubeInfo.modelName=='BP_XSPACE_deng_01_C'){//灯光
  860. this.lightHandle(cube)
  861. }else{
  862. this.updateInfo(cube,oldPosition,scaleX,scaleY);//实例化方法
  863. }
  864. }
  865. },
  866. //更新家具模型到页面中
  867. updateInfo(cube,oldPosition,scaleX,scaleY){
  868. let lay = this.gltfLayouts.find(it=>it.uniId==cube.uniId);
  869. if(cube.instancedMeshIndexList && cube.instancedMeshIndexList.length>0){
  870. cube.instancedMeshIndexList.forEach(item=>{
  871. let index = item.instancedMeshIndex;
  872. let instancedMesh = this.instancedFurList[index];//网格实例对象
  873. let curMeshIndex = item.instancedAtIndex;//当前家具模型在网格实例对象里面的序号
  874. let stratMatrix = new THREE.Matrix4();//定义一个四维矩阵
  875. instancedMesh.getMatrixAt(curMeshIndex,stratMatrix);//获取当前几何体的四维矩阵到stratMatrix里面
  876. let scaleMatrix = new THREE.Matrix4(); //定义一个缩放变化矩阵
  877. let panMatrix = new THREE.Matrix4(); //定义一个平移变化矩阵
  878. if (!lay.loaded) { //说明还没添加到场景中
  879. // scaleMatrix.makeScale(scaleX,1,scaleY); //获得缩放变化矩阵
  880. // panMatrix.makeTranslation(cube.position.x,0,cube.position.z); //获得平移变化矩阵
  881. // stratMatrix.multiply(scaleMatrix).premultiply(panMatrix);//通过矩阵计算获得最终的形变矩阵
  882. // instancedMesh.instanceMatrix.needsUpdate = true;//更新之前,必须开启开关
  883. // instancedMesh.setMatrixAt(curMeshIndex,stratMatrix);//更新几何体的世界矩阵
  884. // this.scene.add(instancedMesh);
  885. }else{//更新形变矩阵
  886. scaleMatrix.makeScale(scaleX, 1, scaleY); //获得缩放变化矩阵
  887. panMatrix.makeTranslation(cube.position.x - oldPosition.x,0,cube.position.z - oldPosition.z); //获得平移变化矩阵
  888. stratMatrix.multiply(scaleMatrix).premultiply(panMatrix);//通过矩阵计算获得最终的形变矩阵
  889. instancedMesh.instanceMatrix.needsUpdate = true;//更新之前,必须开启开关
  890. instancedMesh.setMatrixAt(curMeshIndex,stratMatrix);//更新几何体的世界矩阵
  891. }
  892. })
  893. lay.loaded = true;
  894. }
  895. },
  896. // 空间处理光源
  897. lightHandle(cube){
  898. let light = this.gltfLayouts.find(it=>it.uniId==cube.uniId);
  899. if(!light.loaded){
  900. // 从一个点向各个方向发射的光源。一个常见的例子是模拟一个灯泡发出的光。
  901. let pointLight = new THREE.PointLight(0xffd7b3, 1, 5, 1);
  902. pointLight.position.set(cube.position.x, 1.5, cube.position.z); //default; light shining from top
  903. this.scene.add(pointLight);
  904. let sphereSize = 0.1;
  905. let pointLightHelper = new THREE.PointLightHelper( pointLight, sphereSize );
  906. this.scene.add( pointLightHelper);
  907. // pointLight.castShadow = true; // default false
  908. // // 默认情况下光投影相机区域是一个长宽高为10x10x500的长方体区域,光源投射方向为通过坐标原点
  909. // pointLight.shadow.camera.left = -200; // default
  910. // pointLight.shadow.camera.right = 200; // default
  911. // pointLight.shadow.camera.top = 200; // default
  912. // pointLight.shadow.camera.bottom = -200; // default
  913. this.scene.add(pointLight);
  914. light.loaded = true;
  915. }else{
  916. }
  917. },
  918. // 空间布局旋转镜像重置模型约束
  919. resetModelParameters(curSpace, cubeInfo) {
  920. // 旋转
  921. const defaultLayout = curSpace.layouts.find(item => {
  922. return item.isDefault
  923. })
  924. if (!defaultLayout) {
  925. return cubeInfo
  926. }
  927. let count = 0;
  928. switch (parseInt(defaultLayout.layoutRotate)) {
  929. case 90:
  930. count = 1;
  931. break;
  932. case 180:
  933. count = 2;
  934. break;
  935. case -90:
  936. count = 3;
  937. break;
  938. default:
  939. break;
  940. }
  941. for (let index = 0; index < count; index++) {
  942. let oldCubeInfo = JSON.parse(JSON.stringify(cubeInfo))
  943. oldCubeInfo.isStepAsideLeft = "false"
  944. oldCubeInfo.isStepAsideTop = "false"
  945. oldCubeInfo.isStepAsideRight = "false"
  946. oldCubeInfo.isStepAsideBottom = "false"
  947. oldCubeInfo.referenceModelLeft = "0"
  948. oldCubeInfo.referenceModelTop = "0"
  949. oldCubeInfo.referenceModelRight = "0"
  950. oldCubeInfo.referenceModelBottom = "0"
  951. oldCubeInfo.rotation = "0"
  952. oldCubeInfo.marginLeft = "0";
  953. oldCubeInfo.marginTop = "0";
  954. oldCubeInfo.marginRight = "0";
  955. oldCubeInfo.marginBottom = "0";
  956. // 是否靠墙
  957. if (cubeInfo.isStepAsideLeft == 'true') {
  958. oldCubeInfo.isStepAsideTop = 'true'
  959. }
  960. if (cubeInfo.isStepAsideTop == 'true') {
  961. oldCubeInfo.isStepAsideRight = 'true'
  962. }
  963. if (cubeInfo.isStepAsideRight == 'true') {
  964. oldCubeInfo.isStepAsideBottom = 'true'
  965. }
  966. if (cubeInfo.isStepAsideBottom == 'true') {
  967. oldCubeInfo.isStepAsideLeft = 'true'
  968. }
  969. // 参照物体
  970. if (parseInt(cubeInfo.referenceModelLeft) > 0) {
  971. oldCubeInfo.referenceModelTop = cubeInfo.referenceModelLeft;
  972. }
  973. if (parseInt(cubeInfo.referenceModelTop) > 0) {
  974. oldCubeInfo.referenceModelRight = cubeInfo.referenceModelTop;
  975. }
  976. if (parseInt(cubeInfo.referenceModelRight) > 0) {
  977. oldCubeInfo.referenceModelBottom = cubeInfo.referenceModelRight;
  978. }
  979. if (parseInt(cubeInfo.referenceModelBottom) > 0) {
  980. oldCubeInfo.referenceModelLeft = cubeInfo.referenceModelBottom;
  981. }
  982. // 边距
  983. oldCubeInfo.marginLeft = cubeInfo.marginBottom;
  984. oldCubeInfo.marginTop = cubeInfo.marginLeft;
  985. oldCubeInfo.marginRight = cubeInfo.marginTop;
  986. oldCubeInfo.marginBottom = cubeInfo.marginRight;
  987. oldCubeInfo.modelWidth = cubeInfo.modelHeight;
  988. oldCubeInfo.modelHeight = cubeInfo.modelWidth;
  989. // 旋转
  990. if (parseInt(cubeInfo.rotation) == 0 || parseInt(cubeInfo.rotation) == 90) {
  991. oldCubeInfo.rotation = parseInt(cubeInfo.rotation) + 90;
  992. }
  993. if (parseInt(cubeInfo.rotation) == 180) {
  994. oldCubeInfo.rotation = "-90";
  995. }
  996. if (parseInt(cubeInfo.rotation) == -90) {
  997. oldCubeInfo.rotation = "0";
  998. }
  999. // console.log("旋转前的模型参数X", cubeInfo, oldCubeInfo, defaultLayout)
  1000. cubeInfo = oldCubeInfo;
  1001. // console.log("旋转后的模型参数X", cubeInfo, oldCubeInfo, defaultLayout)
  1002. }
  1003. return cubeInfo;
  1004. },
  1005. // 改变空间模型
  1006. changeLayoutModel(){
  1007. let changeSpaces = [];
  1008. // 去重
  1009. for (let index = 0; index < this.changeSpaces.length; index++) {
  1010. const element = this.changeSpaces[index];
  1011. const findIndex = changeSpaces.findIndex((item)=>{
  1012. return item.spaceId == element.spaceId;
  1013. })
  1014. if(findIndex==-1){
  1015. const findListIndex = this.spaceList.findIndex((item)=>{
  1016. return item.spaceId == element.spaceId;
  1017. })
  1018. if(findListIndex !=-1 && this.spaceList[findListIndex].spaceType!=14){
  1019. changeSpaces.push(this.spaceList[findListIndex])
  1020. }
  1021. }
  1022. }
  1023. console.log("所有变化的空间", changeSpaces)
  1024. this.changeLayouts = [];
  1025. let promise_list = [];
  1026. if(!changeSpaces || changeSpaces.length==0){
  1027. // this.changeLayoutModelState(true); // 显示家具模型
  1028. return false;
  1029. }
  1030. this.clearAllLayoutData();//清除所有空间的家具模型
  1031. for (let index = 0; index < changeSpaces.length; index++) {
  1032. let element = changeSpaces[index];
  1033. let layoutObj = this.arrFrunList.find((item)=>{
  1034. return item.id == element.layoutId;
  1035. })
  1036. console.log("请求布局的对象", layoutObj, element);
  1037. if(layoutObj){
  1038. promise_list.push(
  1039. new Promise((resolve, reject) => {
  1040. this.loadlayoutByID(layoutObj.groupType, element, resolve);
  1041. })
  1042. )
  1043. }else{//空间不存在布局,需要请求布局信息
  1044. promise_list.push(
  1045. new Promise((resolve, reject) => {
  1046. this.loadlayoutByID(element.groupType, element, resolve);
  1047. })
  1048. )
  1049. }
  1050. }
  1051. Promise.all(promise_list).then(()=>{
  1052. this.$nextTick(()=>{
  1053. console.log("新布局替换完成",this.changeLayouts, changeSpaces,this.arrFrunList.map(it=>it.id));
  1054. this.furnHandle(this.changeLayouts, changeSpaces);//先加载变化的空间的布局
  1055. this.updataPageData();//更新数据
  1056. })
  1057. })
  1058. },
  1059. async loadlayoutByID(groupType,spaceObj, resolve){
  1060. let param = {
  1061. "brandId": $config.brandId,
  1062. "houseId": this.curHouseObj.houseId,
  1063. "groupType": groupType
  1064. }
  1065. // 默认的布局
  1066. let res = await requestConfig("findOverallArrangementList", param);
  1067. if (!res.success || !res.pageModel || res.pageModel.resultSet.length == 0) {
  1068. return resolve();
  1069. }
  1070. const groupLayouts = res.pageModel.resultSet;
  1071. console.log("查询指定分组的布局", groupType, groupLayouts, spaceObj.spaceWidth, spaceObj.spaceHeight)
  1072. // 根据空间的尺寸和布局的最小尺寸,筛选出合适的最大的布局
  1073. const layouts01 = groupLayouts.filter((item)=>{
  1074. return item.minWidth <= spaceObj.spaceWidth && item.minDepth <= spaceObj.spaceHeight
  1075. })
  1076. console.log("过滤适合的布局01", layouts01)
  1077. // 长度和宽度都满足空间尺寸
  1078. const layouts02 = layouts01.filter((item)=>{
  1079. return (item.minWidth * item.minDepth ) <= (spaceObj.spaceWidth * spaceObj.spaceHeight)
  1080. })
  1081. console.log("过滤适合的布局02", layouts02)
  1082. // 取布局面积最大的一个
  1083. let layoutObj = null
  1084. for (let index = 0; index < layouts02.length; index++) {
  1085. const element = layouts02[index];
  1086. if(!layoutObj){
  1087. layoutObj = element;
  1088. }else{
  1089. if((layoutObj.minWidth * layoutObj.minDepth) < (element.minWidth * element.minDepth)){
  1090. layoutObj = element;
  1091. }
  1092. }
  1093. }
  1094. if(layoutObj==null){
  1095. console.warn("没有合适的布局", layoutObj,spaceObj.layoutId);
  1096. spaceObj.groupType = groupType;
  1097. this.deleteLayoutModel(spaceObj, layoutObj);//删除当前的布局
  1098. return resolve()
  1099. }
  1100. console.log("找出最合适的布局", layoutObj)
  1101. console.log("更新空间的布局ID=", spaceObj.layoutId,'=>',layoutObj.id)
  1102. // 合适的布局更现有布局相同-不在需要了,因为这此之前已经把所有的家具都删除了
  1103. // if(spaceObj.layoutId == layoutObj.id && !spaceObj.delateLayoutId){
  1104. // // this.calculateLayoutModelSizeBySpace(spaceObj) // 提前计算模型的位置
  1105. // // this.changeLayoutModelState(true); // 显示家具模型
  1106. // return resolve()
  1107. // }
  1108. // 更新空间的布局id
  1109. const element = this.spaceList.find(it=>it.spaceId == spaceObj.spaceId);
  1110. if(element){
  1111. this.deleteLayoutModel(element, layoutObj)
  1112. element.layoutId = layoutObj.id
  1113. console.log("替换空间的布局ID", spaceObj.spaceId, layoutObj.id);
  1114. }
  1115. this.changeLayouts.push(layoutObj)
  1116. resolve()
  1117. }
  1118. }
  1119. }