loadModel.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  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. arrFrunList:[],
  15. promise_list:[],
  16. // loadFurPromise: new Promise((resolve) => {
  17. // this.loadedCompleteFun = function() {
  18. // console.log('家具模型接口结束');
  19. // resolve()
  20. // }
  21. // }),
  22. dracoLoader:null,
  23. type:1,
  24. tmpList:[],
  25. realList:[],
  26. }
  27. },
  28. watch: {},
  29. mounted() {
  30. console.warn("***loadmodel-mounted****")
  31. this.dracoLoader = new DRACOLoader();
  32. this.dracoLoader.setDecoderPath('/gltf/');
  33. this.dracoLoader.setDecoderConfig( { type: 'js' } );
  34. this.dracoLoader.preload();
  35. },
  36. methods: {
  37. // 设置空间数组的墙体信息
  38. async setSpaceListWallInfo(){
  39. for (let index = 0; index < this.spaceList.length; index++) {
  40. let spaceWallInfo = {wallN:false, wallS:false, wallW:false, wallE:false}
  41. const element = this.spaceList[index];
  42. const wallWIndex = this.gltfWalls.findIndex(item=>{
  43. return element.spaceId == item.spaceId && item.wallDirection == "W"
  44. })
  45. spaceWallInfo.wallW = wallWIndex == -1 ? false : true;
  46. const wallEIndex = this.gltfWalls.findIndex(item=>{
  47. return element.spaceId == item.spaceId && item.wallDirection == "E"
  48. })
  49. spaceWallInfo.wallE = wallEIndex == -1 ? false : true;
  50. const wallNIndex = this.gltfWalls.findIndex(item=>{
  51. return element.spaceId == item.spaceId && item.wallDirection == "N"
  52. })
  53. spaceWallInfo.wallN = wallNIndex == -1 ? false : true;
  54. const wallSIndex = this.gltfWalls.findIndex(item=>{
  55. return element.spaceId == item.spaceId && item.wallDirection == "S"
  56. })
  57. spaceWallInfo.wallS = wallSIndex == -1 ? false : true;
  58. element.spaceWallInfo = spaceWallInfo;
  59. }
  60. // this.loadedCompleteFun();
  61. },
  62. // 批量获取空间模型信息
  63. async getOverallArrangementDetailsList(type=1) {
  64. // 设置空间数组的墙体信息
  65. // this.setSpaceListWallInfo();
  66. this.type = type;//加载类型,1空间加载 2 全局精简加载
  67. let arr = this.spaceList.map(it => it.layoutId).filter(it => it != 0);
  68. let parmas = {
  69. ids: arr,
  70. };
  71. // this.loadFurPromise = new Promise((resolve, reject) => {
  72. // this.loadedCompleteFun = function() {
  73. // console.log('家具模型接口结束');
  74. // resolve()
  75. // }
  76. // })
  77. let res = await requestConfig("getOverallArrangementDetailsList", parmas);
  78. if (!res.success || !res.list || res.list.length == 0) {
  79. return false;
  80. }
  81. this.promise_list = [];
  82. this.arrFrunList = res.list;
  83. this.furnHandle();
  84. },
  85. //拆分家具模型加载逻辑
  86. furnHandle(){
  87. let startTime = new Date().getTime();
  88. let tmpList = [];//临时数据
  89. this.gltfLayouts = []; //模型列表,所有空间里面的每个模型(家具)对应一条记录
  90. let allowSpaceId = [this.curSpaceObj.spaceId];
  91. if(this.type == 2){//全局精简模型;需要的是所有空间的模型
  92. allowSpaceId = this.spaceList.map(it=>it.spaceId)
  93. }else{//空间模型模式
  94. allowSpaceId = [this.curSpaceObj.spaceId];
  95. if(this.curSpaceObj.spaceId==758){//二层主卧特殊处理
  96. allowSpaceId.push(735);//休闲小客厅
  97. }
  98. //花园类型的添加到家具加载目录里面
  99. // this.spaceList.forEach(it=>{
  100. // if(it.spaceType==14){
  101. // allowSpaceId.push(it.spaceId);
  102. // }
  103. // })
  104. }
  105. // allowSpaceId = [388];//模型有警告,需要看下
  106. this.arrFrunList.forEach(signel => {
  107. let spaceId = this.spaceList.find(it => it.layoutId == signel.id).spaceId;
  108. if(allowSpaceId.includes(spaceId)){//只加载允许的空间的布局,其他不加载
  109. let md = JSON.parse(signel.modelJson); //获取布局里面的模型信息
  110. console.warn("***布局***", md, signel.id)
  111. //遍历模型信息,获取模型列表
  112. for (let i = 0; i < md.modelData.length; i++) {
  113. let item = md.modelData[i];
  114. item.spaceId = spaceId;
  115. item.layoutId = signel.id;
  116. item.h5Id = signel.id+""+item.id;//唯一标识
  117. if(item.modelName=='BP_furnitureBase_C'){
  118. continue;
  119. }else{
  120. tmpList.push(item);
  121. }
  122. }
  123. }
  124. })
  125. this.tmpList = tmpList;
  126. if(this.type==2){//全局精简模型;需要的是所有空间的模型
  127. this.fliterList(tmpList);
  128. console.warn("***fliterList***",this.realList.length ,this.realList);
  129. tmpList = this.realList;
  130. }
  131. let realFurArr = [];
  132. realFurArr = this.preFurnitureData(tmpList);//统一处理家具模型
  133. this.calculateLayoutModelSize() // 提前计算模型的位置
  134. console.log("***realFurArr***", realFurArr,this.gltfLayouts);
  135. realFurArr && realFurArr.forEach((item,index) => {
  136. this.promise_list.push(
  137. new Promise((resolve, reject) => {
  138. this.loadLayoutModels(item, resolve);
  139. })
  140. )
  141. });
  142. Promise.all(this.promise_list).then(() => {
  143. let endTime = new Date().getTime();
  144. console.log("家具模型全部加载完成,时间:", endTime - startTime);
  145. })
  146. },
  147. //过滤掉不需要的家具
  148. fliterList(list){
  149. this.realList = [];
  150. //找到直接的家具模型
  151. list && list.forEach((mod)=>{
  152. let name = mod.modelName.substring(0,mod.modelName.length-2);
  153. if(globlShowModel.includes(name)){
  154. this.realList.push(mod);
  155. }
  156. })
  157. this.realList.forEach((ref)=>{
  158. this.recursionFliter(ref)
  159. })
  160. },
  161. //递归处理不需要的家具
  162. recursionFliter(item){
  163. let _list = [];//
  164. if(parseInt(item.referenceModelBottom) > 0){
  165. _list.push(item.referenceModelBottom)
  166. }
  167. if(parseInt(item.referenceModelLeft) > 0){
  168. _list.push(item.referenceModelLeft)
  169. }
  170. if(parseInt(item.referenceModelRight) > 0){
  171. _list.push(item.referenceModelRight)
  172. }
  173. if(parseInt(item.referenceModelTop) > 0){
  174. _list.push(item.referenceModelTop)
  175. }
  176. if(_list.length==0){
  177. return false;
  178. }else{
  179. this.tmpList.forEach(tmp=>{
  180. if(_list.includes(tmp.id)){
  181. if(!this.realList.find(it=>it.h5Id==tmp.h5Id)){
  182. this.realList.push(tmp);
  183. this.recursionFliter(tmp);
  184. }
  185. }
  186. })
  187. }
  188. },
  189. //预处理需要加载墙体模型的数据-减少模型请求数
  190. preFurnitureData(list){
  191. let realFurnitureArr = [];//家具列表
  192. list && list.forEach((item, index) => {
  193. item.uniId = Date.now() + index;//唯一标识
  194. //获取墙体对应的gltb模型的相关信息
  195. let modelName = item.modelName;
  196. // console.log("布局模型名称", modelName);
  197. let layoutModel = modelData.find(it => modelName.indexOf(it.modelName) == 0); //模型地址
  198. if (layoutModel && layoutModel.url) {//该数据存在模型地址
  199. let object = realFurnitureArr.find(it=>it.url==layoutModel.url);
  200. //列表中还没有这个数据
  201. if(!object){
  202. let it = {
  203. url:layoutModel.url,
  204. name:layoutModel.modelName,
  205. list:[item],
  206. }
  207. realFurnitureArr.push(it)
  208. }else{
  209. object.list.push(item);
  210. }
  211. let position = new THREE.Vector3();//当前几何体的位置参数
  212. let scale = new THREE.Vector3();//当前几何体的缩放参数
  213. let rotation = new THREE.Vector3();//当前几何体的缩放参数
  214. let md = {
  215. uniId:item.uniId,//家具模型实例的唯一标识
  216. spaceId:item.spaceId,
  217. id:item.id,
  218. userData:item,
  219. position:position,
  220. scale:scale,
  221. rotation:rotation,
  222. loaded:false,
  223. };
  224. this.gltfLayouts.push(md);
  225. }
  226. });
  227. return realFurnitureArr;
  228. },
  229. //加载家具模型-实例化方案
  230. loadLayoutModels(realData, resolve){
  231. var that = this;
  232. if(!realData.url){
  233. console.warn("***家具模型不存在***",realData);
  234. resolve();
  235. return false;
  236. }
  237. if(realData.name.includes('BP_XSPACE_deng_01')){//灯光
  238. resolve();
  239. }else{
  240. that.loader.setDRACOLoader(this.dracoLoader);
  241. that.loader.load(realData.url, ( gltf ) => {
  242. gltf.scene.traverse((child)=> {
  243. if (child.isMesh && child.visible) {
  244. let instancedMesh = new THREE.InstancedMesh(child.geometry.clone(), child.material.clone(), realData.list.length);
  245. this.instancedFurList.push(instancedMesh);
  246. //realData 该模型被重复使用时的每一次的形变参数等
  247. realData.list && realData.list.forEach((it,i)=>{
  248. let gltfFurn = that.gltfLayouts.find(itme=>itme.uniId==it.uniId);//判断是否已经添加过
  249. if(!gltfFurn){
  250. return false;
  251. // debugger
  252. }
  253. gltf.scene.rotation.y = gltfFurn.rotation.y;
  254. gltf.scene.position.set(gltfFurn.position.x,0,gltfFurn.position.z);
  255. gltf.scene.scale.set(gltfFurn.scale.x,1,gltfFurn.scale.z);
  256. gltf.scene.updateMatrixWorld();//更新世界坐标-这样,子模型也同步更新了
  257. instancedMesh.setMatrixAt(i, child.matrixWorld);
  258. instancedMesh.instanceMatrix.needsUpdate = true;
  259. gltfFurn.loaded = true;
  260. if(!gltfFurn.instancedMeshIndexList){//标识网格实例数组的序号 以及 当前几何体 在网格实例的序号
  261. gltfFurn.instancedMeshIndexList = [
  262. {instancedMeshIndex:this.instancedFurList.length-1,instancedAtIndex:i},
  263. ]
  264. }else{
  265. gltfFurn.instancedMeshIndexList.push({
  266. instancedMeshIndex:this.instancedFurList.length-1,instancedAtIndex:i
  267. })
  268. }
  269. })
  270. instancedMesh.userType = "layoutMesh";
  271. if(realData.name.includes("BP_L_carpet01")){//地毯接收阴影
  272. instancedMesh.receiveShadow = true;//对象是否接收阴影
  273. }else{
  274. instancedMesh.castShadow = true;//对象是否产生阴影
  275. }
  276. this.scene.add(instancedMesh);//添加到场景中
  277. }
  278. });
  279. resolve();
  280. });
  281. }
  282. },
  283. //加载模型
  284. loadLayoutModelsOld(modelObj, resolve) {
  285. let that = this;
  286. const modelName = modelObj.modelName;
  287. console.log("布局模型名称", modelName);
  288. let layoutModel = modelData.find(it => modelName.indexOf(it.modelName) == 0); //模型地址
  289. if (!layoutModel || !layoutModel.url) {
  290. resolve();
  291. return false
  292. }
  293. let url = layoutModel.url;
  294. console.log("布局模型数据", layoutModel);
  295. that.loader.load(url, (gltf) => {
  296. // console.log("布局模型加载成功", gltf);
  297. let model = gltf.scene; // 获取模型
  298. model.name = layoutModel.modelName;
  299. model.userType = "layoutMesh";
  300. model.userData = modelObj;
  301. // model.rotation.y = Math.PI / 2 ; // 旋转 90 度
  302. this.gltfLayouts.push(model);
  303. resolve();
  304. });
  305. },
  306. // 计算家具的位置
  307. calculateLayoutModelSize() {
  308. console.log("计算家具的位置", this.gltfLayouts);
  309. for (let index = 0; index < this.spaceList.length; index++) {
  310. const element = this.spaceList[index];
  311. const gltfLayoutModels = this.gltfLayouts.filter(item => {
  312. return element.layoutId == item.userData.layoutId && element.spaceId == item.userData.spaceId;
  313. })
  314. //空间下不存在家具模型,则该空间不需要进行下一步处理
  315. if (!gltfLayoutModels || gltfLayoutModels.length == 0) {
  316. continue;
  317. }
  318. gltfLayoutModels.sort(function(a, b) {
  319. return a.userData.level - b.userData.level
  320. });
  321. // console.log("对应空间ID的模型数组", this.gltfLayouts, element.spaceId, gltfLayoutModels)
  322. for (let j = 0; j < gltfLayoutModels.length; j++) {
  323. const cube = gltfLayoutModels[j];
  324. this.drawLayoutModel(element, cube);
  325. }
  326. }
  327. },
  328. // 绘制模型
  329. drawLayoutModel(curSpace, cube) {
  330. const {
  331. centerX,
  332. spaceId
  333. } = curSpace;
  334. const cubeInfo = this.resetModelParameters(curSpace, cube.userData);
  335. // const cubeInfo = cube.userData;
  336. let centerY = curSpace.centerY * -1; // UE和ThreeJS坐标做相反
  337. // 默认空间中心点
  338. let positionX = centerX;
  339. let positionY = centerY;
  340. let rotationY = Math.PI / 2;
  341. let scaleX = 1;
  342. let scaleY = 1;
  343. // 空间尺寸
  344. let spaceWidth = curSpace.spaceWidth;
  345. let spaceHeight = curSpace.spaceHeight;
  346. // 模型尺寸
  347. let modelWidth = cubeInfo.modelWidth;
  348. let modelHeight = cubeInfo.modelHeight;
  349. // 判断旋转
  350. if (parseFloat(cubeInfo.rotation) == 90) {
  351. rotationY = 0;
  352. // 交换尺寸
  353. // modelWidth = cubeInfo.modelHeight;
  354. // modelHeight = cubeInfo.modelWidth;
  355. }
  356. if (parseFloat(cubeInfo.rotation) == 180) {
  357. rotationY = -Math.PI / 2;
  358. // modelWidth = cubeInfo.modelHeight;
  359. // modelHeight = cubeInfo.modelWidth;
  360. }
  361. if (parseFloat(cubeInfo.rotation) == -90) {
  362. rotationY = -Math.PI;
  363. // 交换尺寸
  364. // modelWidth = cubeInfo.modelHeight;
  365. // modelHeight = cubeInfo.modelWidth;
  366. }
  367. // 判断靠墙
  368. if (cubeInfo.isStepAsideLeft == 'true') {
  369. positionX = centerX - (spaceWidth / 2 - modelWidth / 2);
  370. if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
  371. positionX = centerX - (spaceWidth / 2 - modelWidth / 2);
  372. }
  373. positionX += parseFloat(cubeInfo.marginLeft);
  374. positionX += curSpace.spaceWallInfo.wallW ? 10 : 0;
  375. }
  376. if (cubeInfo.isStepAsideRight == 'true') {
  377. positionX = centerX + (spaceWidth / 2 - modelWidth / 2);
  378. if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
  379. positionX = centerX + (spaceWidth / 2 - modelWidth / 2);
  380. }
  381. positionX -= parseFloat(cubeInfo.marginRight);
  382. positionX -= curSpace.spaceWallInfo.wallE ? 10 : 0;
  383. }
  384. if (cubeInfo.isStepAsideTop == 'true') {
  385. positionY = centerY - (spaceHeight / 2 - modelHeight / 2);
  386. if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
  387. positionY = centerY - (spaceHeight / 2 - modelHeight / 2);
  388. }
  389. positionY += parseFloat(cubeInfo.marginTop);
  390. positionY += curSpace.spaceWallInfo.wallN ? 10 : 0;
  391. }
  392. if (cubeInfo.isStepAsideBottom == 'true') {
  393. positionY = centerY + (spaceHeight / 2 - modelHeight / 2);
  394. if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
  395. positionY = centerY + (spaceHeight / 2 - modelHeight / 2);
  396. }
  397. positionY -= parseFloat(cubeInfo.marginBottom);
  398. positionY -= curSpace.spaceWallInfo.wallS ? 10 : 0;
  399. }
  400. // 参照物
  401. if (parseInt(cubeInfo.referenceModelTop) > 0) {
  402. const referenceModel = this.gltfLayouts.find(item => {
  403. const layoutModelData = item.userData;
  404. return layoutModelData.id == parseInt(cubeInfo.referenceModelTop) && layoutModelData
  405. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  406. })
  407. if(!referenceModel){
  408. console.warn("***no-data***",cubeInfo.referenceModelTop,cubeInfo)
  409. return false
  410. }
  411. positionY = referenceModel.position.z * 100 + (referenceModel.userData.modelHeight / 2 + cubeInfo
  412. .modelHeight / 2);
  413. positionY = positionY + parseFloat(cubeInfo.marginTop);
  414. }
  415. if (parseInt(cubeInfo.referenceModelBottom) > 0) {
  416. const referenceModel = this.gltfLayouts.find(item => {
  417. const layoutModelData = item.userData;
  418. return layoutModelData.id == parseInt(cubeInfo.referenceModelBottom) && layoutModelData
  419. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  420. })
  421. if(!referenceModel){
  422. console.warn("***no-data***",cubeInfo.referenceModelBottom,cubeInfo)
  423. return false
  424. }
  425. positionY = referenceModel.position.z * 100 - (referenceModel.userData.modelHeight / 2 + cubeInfo
  426. .modelHeight / 2);
  427. positionY = positionY - parseFloat(cubeInfo.marginBottom);
  428. }
  429. if (parseInt(cubeInfo.referenceModelLeft) > 0) {
  430. const referenceModel = this.gltfLayouts.find(item => {
  431. const layoutModelData = item.userData;
  432. return layoutModelData.id == parseInt(cubeInfo.referenceModelLeft) && layoutModelData
  433. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  434. })
  435. if(!referenceModel){
  436. console.warn("***no-data***",cubeInfo.referenceModelLeft,cubeInfo)
  437. return false
  438. }
  439. positionX = referenceModel.position.x * 100 + (referenceModel.userData.modelWidth / 2 + cubeInfo
  440. .modelWidth / 2);
  441. positionX = positionX + parseFloat(cubeInfo.marginLeft);
  442. }
  443. if (parseInt(cubeInfo.referenceModelRight) > 0) {
  444. const referenceModel = this.gltfLayouts.find(item => {
  445. const layoutModelData = item.userData;
  446. return layoutModelData.id == parseInt(cubeInfo.referenceModelRight) && layoutModelData
  447. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  448. })
  449. if(!referenceModel){
  450. console.warn("***no-data***",cubeInfo.referenceModelRight,cubeInfo)
  451. return false
  452. }
  453. positionX = referenceModel.position.x * 100 - (referenceModel.userData.modelWidth / 2 + cubeInfo
  454. .modelWidth / 2);
  455. positionX = positionX - parseFloat(cubeInfo.marginRight);
  456. }
  457. if (cubeInfo.isFixedWidth == "false" || cubeInfo.isFixedHeight == "false") { // 固定尺寸
  458. // 靠墙拉伸
  459. if (cubeInfo.isStepAsideTop == 'true' && cubeInfo.isStepAsideBottom == 'true') {
  460. // console.log("高度拉伸", spaceHeight / modelHeight)
  461. positionY = centerY;
  462. if (curSpace.spaceWallInfo.wallN && curSpace.spaceWallInfo.wallS) {
  463. spaceHeight -= 20 + parseFloat(cubeInfo.marginTop) + parseFloat(cubeInfo.marginBottom);
  464. } else if (curSpace.spaceWallInfo.wallN) {
  465. spaceHeight -= 10 + parseFloat(cubeInfo.marginTop);
  466. positionY += 10 / 2;
  467. positionY += parseFloat(cubeInfo.marginTop) / 2;
  468. } else if (curSpace.spaceWallInfo.wallS) {
  469. spaceHeight -= 10 + parseFloat(cubeInfo.marginBottom);
  470. positionY -= 10 / 2;
  471. positionY -= parseFloat(cubeInfo.marginBottom) / 2;
  472. }else {
  473. spaceHeight -= parseFloat(cubeInfo.marginTop) + parseFloat(cubeInfo.marginBottom);
  474. positionY += parseFloat(cubeInfo.marginTop) / 2 ;
  475. positionY -= parseFloat(cubeInfo.marginBottom) / 2;
  476. }
  477. // 计算缩放
  478. if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
  479. scaleY = spaceHeight / modelHeight;
  480. } else {
  481. scaleX = spaceHeight / modelHeight;
  482. }
  483. }
  484. if (cubeInfo.isStepAsideLeft == 'true' && cubeInfo.isStepAsideRight == 'true') {
  485. // console.log("宽度拉伸11111", spaceWidth / modelWidth)
  486. positionX = centerX;
  487. if (curSpace.spaceWallInfo.wallW && curSpace.spaceWallInfo.wallE) {
  488. spaceWidth -= 20 + parseFloat(cubeInfo.marginLeft) + parseFloat(cubeInfo.marginRight);;
  489. } else if (curSpace.spaceWallInfo.wallW) {
  490. spaceWidth -= 10 + parseFloat(cubeInfo.marginLeft);
  491. positionX += 10 / 2;
  492. positionX += parseFloat(cubeInfo.marginLeft) / 2;
  493. } else if (curSpace.spaceWallInfo.wallE) {
  494. spaceWidth -= 10 + parseFloat(cubeInfo.marginRight);
  495. positionX -= 10 / 2;
  496. positionX -= parseFloat(cubeInfo.marginRight) / 2;
  497. }else {
  498. spaceWidth -= parseFloat(cubeInfo.marginLeft) + parseFloat(cubeInfo.marginRight);
  499. positionX += parseFloat(cubeInfo.marginLeft) / 2;
  500. positionX -= parseFloat(cubeInfo.marginRight) / 2;
  501. }
  502. // console.log("模型计算位置" , parseFloat(cubeInfo.rotation))
  503. // 计算缩放
  504. if (parseFloat(cubeInfo.rotation) == 90 || parseFloat(cubeInfo.rotation) == -90) {
  505. scaleX = spaceWidth / modelWidth;
  506. } else {
  507. scaleY = spaceWidth / modelWidth;
  508. }
  509. }
  510. // 单个参照物和墙面拉伸
  511. if (cubeInfo.isStepAsideTop == 'true' && parseInt(cubeInfo.referenceModelBottom) > 0) {
  512. const referenceModel = this.gltfLayouts.find(item => {
  513. const layoutModelData = item.userData;
  514. return layoutModelData.id == parseInt(cubeInfo.referenceModelBottom) && layoutModelData
  515. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  516. })
  517. const referenceModelPositionY = referenceModel.position.z * 100 - referenceModel.userData
  518. .modelHeight / 2 - parseFloat(cubeInfo.marginBottom);
  519. const wallPositionY = centerY - spaceHeight / 2 + (curSpace.spaceWallInfo.wallN ? 10 : 0) +
  520. parseFloat(cubeInfo.marginTop);
  521. const newModelHeight = Math.abs(referenceModelPositionY - wallPositionY);
  522. // console.log("上边拉伸", referenceModelPositionY, wallPositionY, newModelHeight)
  523. if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
  524. scaleY = newModelHeight / modelHeight;
  525. } else {
  526. scaleX = newModelHeight / modelHeight;
  527. }
  528. positionY = wallPositionY + newModelHeight / 2;
  529. }
  530. if (cubeInfo.isStepAsideBottom == 'true' && parseInt(cubeInfo.referenceModelTop) > 0) {
  531. const referenceModel = this.gltfLayouts.find(item => {
  532. const layoutModelData = item.userData;
  533. return layoutModelData.id == parseInt(cubeInfo.referenceModelTop) && layoutModelData
  534. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  535. })
  536. const referenceModelPositionY = referenceModel.position.z * 100 + referenceModel.userData
  537. .modelHeight / 2 + parseFloat(cubeInfo.marginTop) + (curSpace.spaceWallInfo.wallN ? 10 : 0);
  538. const wallPositionY = centerY + spaceHeight / 2 - (curSpace.spaceWallInfo.wallS ? 10 : 0) -
  539. parseFloat(cubeInfo.marginBottom);
  540. const newModelHeight = Math.abs(referenceModelPositionY - wallPositionY);
  541. if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
  542. scaleY = newModelHeight / modelHeight;
  543. } else {
  544. scaleX = newModelHeight / modelHeight;
  545. }
  546. positionY = wallPositionY - newModelHeight / 2;
  547. }
  548. if (cubeInfo.isStepAsideLeft == 'true' && parseInt(cubeInfo.referenceModelRight) > 0) {
  549. // console.log("左边拉伸")
  550. const referenceModel = this.gltfLayouts.find(item => {
  551. const layoutModelData = item.userData;
  552. return layoutModelData.id == parseInt(cubeInfo.referenceModelRight) && layoutModelData
  553. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  554. })
  555. const referenceModelPositionX = referenceModel.position.x * 100 - referenceModel.userData
  556. .modelWidth / 2 - parseFloat(cubeInfo.marginLeft);
  557. const wallPositionX = centerX - spaceWidth / 2 + (curSpace.spaceWallInfo.wallE ? 10 : 0) +
  558. parseFloat(cubeInfo.marginRight);
  559. const newModelWidth = Math.abs(referenceModelPositionX - wallPositionX);
  560. if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
  561. scaleX = newModelWidth / modelWidth;
  562. } else {
  563. scaleY = newModelWidth / modelWidth;
  564. }
  565. positionX = wallPositionX + newModelWidth / 2;
  566. }
  567. if (cubeInfo.isStepAsideRight == 'true' && parseInt(cubeInfo.referenceModelLeft) > 0) {
  568. const referenceModel = this.gltfLayouts.find(item => {
  569. const layoutModelData = item.userData;
  570. return layoutModelData.id == parseInt(cubeInfo.referenceModelLeft) && layoutModelData
  571. .spaceId == cubeInfo.spaceId && layoutModelData.layoutId == cubeInfo.layoutId;
  572. })
  573. const referenceModelPositionX = referenceModel.position.x * 100 + referenceModel.userData
  574. .modelWidth / 2 + parseFloat(cubeInfo.marginLeft);
  575. const wallPositionX = centerX + spaceWidth / 2 - (curSpace.spaceWallInfo.wallE ? 10 : 0) -
  576. parseFloat(cubeInfo.marginRight);
  577. const newModelWidth = Math.abs(referenceModelPositionX - wallPositionX);
  578. if (Math.abs(parseFloat(cubeInfo.rotation)) == 90) {
  579. scaleX = newModelWidth / modelWidth;
  580. } else {
  581. scaleY = newModelWidth / modelWidth;
  582. }
  583. positionX = wallPositionX - newModelWidth / 2;
  584. // console.log("右边拉伸", Math.abs(parseFloat(cubeInfo.rotation)))
  585. }
  586. }
  587. // console.log("模型计算位置", cubeInfo, centerX, centerY, spaceWidth, spaceHeight, modelWidth, modelHeight, spaceId, scaleX, scaleY, positionX, positionY)
  588. let oldPosition = new THREE.Vector3();//当前几何体的位置参数
  589. oldPosition.copy(cube.position);
  590. cube.position.x = positionX / 100;
  591. cube.position.z = positionY / 100;
  592. cube.rotation.y = rotationY;
  593. cube.scale.x = scaleX;
  594. cube.scale.z = scaleY;
  595. cube.scale.y = 1;
  596. // if (!cube.parent) { //说明还没添加到场景中-旧版方法
  597. // this.scene.add(cube); //处理完毕后在加入场景中
  598. // }
  599. // if(scaleX>1 || scaleY>1){
  600. // console.warn("***scaleinfo***",cubeInfo.id,scaleX,scaleY,cubeInfo.modelName)
  601. // }
  602. if(this.type==2){//全局精简加载
  603. let name = cubeInfo.modelName.substring(0, cubeInfo.modelName.length - 2);
  604. if(globlShowModel.includes(name)){
  605. if(cubeInfo.modelName=='BP_XSPACE_deng_01_C'){//灯光
  606. this.lightHandle(cube)
  607. }else{
  608. this.updateInfo(cube,oldPosition,scaleX,scaleY);//实例化方法
  609. }
  610. }
  611. }else{
  612. if(cubeInfo.modelName=='BP_XSPACE_deng_01_C'){//灯光
  613. this.lightHandle(cube)
  614. }else{
  615. this.updateInfo(cube,oldPosition,scaleX,scaleY);//实例化方法
  616. }
  617. }
  618. },
  619. //更新家具模型到页面中
  620. updateInfo(cube,oldPosition,scaleX,scaleY){
  621. let lay = this.gltfLayouts.find(it=>it.uniId==cube.uniId);
  622. if(cube.instancedMeshIndexList && cube.instancedMeshIndexList.length>0){
  623. cube.instancedMeshIndexList.forEach(item=>{
  624. let index = item.instancedMeshIndex;
  625. let instancedMesh = this.instancedFurList[index];//网格实例对象
  626. let curMeshIndex = item.instancedAtIndex;//当前家具模型在网格实例对象里面的序号
  627. let stratMatrix = new THREE.Matrix4();//定义一个四维矩阵
  628. instancedMesh.getMatrixAt(curMeshIndex,stratMatrix);//获取当前几何体的四维矩阵到stratMatrix里面
  629. let scaleMatrix = new THREE.Matrix4(); //定义一个缩放变化矩阵
  630. let panMatrix = new THREE.Matrix4(); //定义一个平移变化矩阵
  631. if (!lay.loaded) { //说明还没添加到场景中
  632. // scaleMatrix.makeScale(scaleX,1,scaleY); //获得缩放变化矩阵
  633. // panMatrix.makeTranslation(cube.position.x,0,cube.position.z); //获得平移变化矩阵
  634. // stratMatrix.multiply(scaleMatrix).premultiply(panMatrix);//通过矩阵计算获得最终的形变矩阵
  635. // instancedMesh.instanceMatrix.needsUpdate = true;//更新之前,必须开启开关
  636. // instancedMesh.setMatrixAt(curMeshIndex,stratMatrix);//更新几何体的世界矩阵
  637. // this.scene.add(instancedMesh);
  638. }else{//更新形变矩阵
  639. panMatrix.makeTranslation(cube.position.x - oldPosition.x,0,cube.position.z - oldPosition.z); //获得平移变化矩阵
  640. stratMatrix.premultiply(panMatrix);//通过矩阵计算获得最终的形变矩阵
  641. instancedMesh.instanceMatrix.needsUpdate = true;//更新之前,必须开启开关
  642. instancedMesh.setMatrixAt(curMeshIndex,stratMatrix);//更新几何体的世界矩阵
  643. }
  644. })
  645. lay.loaded = true;
  646. }
  647. },
  648. // 空间处理光源
  649. lightHandle(cube){
  650. let light = this.gltfLayouts.find(it=>it.uniId==cube.uniId);
  651. if(!light.loaded){
  652. // 从一个点向各个方向发射的光源。一个常见的例子是模拟一个灯泡发出的光。
  653. let pointLight = new THREE.PointLight(0xffd7b3, 1, 5, 1);
  654. pointLight.position.set(cube.position.x, 1.5, cube.position.z); //default; light shining from top
  655. this.scene.add(pointLight);
  656. let sphereSize = 0.1;
  657. let pointLightHelper = new THREE.PointLightHelper( pointLight, sphereSize );
  658. this.scene.add( pointLightHelper);
  659. // pointLight.castShadow = true; // default false
  660. // // 默认情况下光投影相机区域是一个长宽高为10x10x500的长方体区域,光源投射方向为通过坐标原点
  661. // pointLight.shadow.camera.left = -200; // default
  662. // pointLight.shadow.camera.right = 200; // default
  663. // pointLight.shadow.camera.top = 200; // default
  664. // pointLight.shadow.camera.bottom = -200; // default
  665. this.scene.add(pointLight);
  666. light.loaded = true;
  667. }else{
  668. }
  669. },
  670. // 空间布局旋转镜像重置模型约束
  671. resetModelParameters(curSpace, cubeInfo) {
  672. // 旋转
  673. const defaultLayout = curSpace.layouts.find(item => {
  674. return item.isDefault
  675. })
  676. if (!defaultLayout) {
  677. return cubeInfo
  678. }
  679. let count = 0;
  680. switch (parseInt(defaultLayout.layoutRotate)) {
  681. case 90:
  682. count = 1;
  683. break;
  684. case 180:
  685. count = 2;
  686. break;
  687. case -90:
  688. count = 3;
  689. break;
  690. default:
  691. break;
  692. }
  693. for (let index = 0; index < count; index++) {
  694. let oldCubeInfo = JSON.parse(JSON.stringify(cubeInfo))
  695. oldCubeInfo.isStepAsideLeft = "false"
  696. oldCubeInfo.isStepAsideTop = "false"
  697. oldCubeInfo.isStepAsideRight = "false"
  698. oldCubeInfo.isStepAsideBottom = "false"
  699. oldCubeInfo.referenceModelLeft = "0"
  700. oldCubeInfo.referenceModelTop = "0"
  701. oldCubeInfo.referenceModelRight = "0"
  702. oldCubeInfo.referenceModelBottom = "0"
  703. oldCubeInfo.rotation = "0"
  704. oldCubeInfo.marginLeft = "0";
  705. oldCubeInfo.marginTop = "0";
  706. oldCubeInfo.marginRight = "0";
  707. oldCubeInfo.marginBottom = "0";
  708. // 是否靠墙
  709. if (cubeInfo.isStepAsideLeft == 'true') {
  710. oldCubeInfo.isStepAsideTop = 'true'
  711. }
  712. if (cubeInfo.isStepAsideTop == 'true') {
  713. oldCubeInfo.isStepAsideRight = 'true'
  714. }
  715. if (cubeInfo.isStepAsideRight == 'true') {
  716. oldCubeInfo.isStepAsideBottom = 'true'
  717. }
  718. if (cubeInfo.isStepAsideBottom == 'true') {
  719. oldCubeInfo.isStepAsideLeft = 'true'
  720. }
  721. // 参照物体
  722. if (parseInt(cubeInfo.referenceModelLeft) > 0) {
  723. oldCubeInfo.referenceModelTop = cubeInfo.referenceModelLeft;
  724. }
  725. if (parseInt(cubeInfo.referenceModelTop) > 0) {
  726. oldCubeInfo.referenceModelRight = cubeInfo.referenceModelTop;
  727. }
  728. if (parseInt(cubeInfo.referenceModelRight) > 0) {
  729. oldCubeInfo.referenceModelBottom = cubeInfo.referenceModelRight;
  730. }
  731. if (parseInt(cubeInfo.referenceModelBottom) > 0) {
  732. oldCubeInfo.referenceModelLeft = cubeInfo.referenceModelBottom;
  733. }
  734. // 边距
  735. oldCubeInfo.marginLeft = cubeInfo.marginTop;
  736. oldCubeInfo.marginTop = cubeInfo.marginRight;
  737. oldCubeInfo.marginRight = cubeInfo.marginBottom;
  738. oldCubeInfo.marginBottom = cubeInfo.marginLeft;
  739. oldCubeInfo.modelWidth = cubeInfo.modelHeight;
  740. oldCubeInfo.modelHeight = cubeInfo.modelWidth;
  741. // 旋转
  742. if (parseInt(cubeInfo.rotation) == 0 || parseInt(cubeInfo.rotation) == 90) {
  743. oldCubeInfo.rotation = parseInt(cubeInfo.rotation) + 90;
  744. }
  745. if (parseInt(cubeInfo.rotation) == 180) {
  746. oldCubeInfo.rotation = "-90";
  747. }
  748. if (parseInt(cubeInfo.rotation) == -90) {
  749. oldCubeInfo.rotation = "0";
  750. }
  751. // console.log("旋转前的模型参数X", cubeInfo, oldCubeInfo, defaultLayout)
  752. cubeInfo = oldCubeInfo;
  753. // console.log("旋转后的模型参数X", cubeInfo, oldCubeInfo, defaultLayout)
  754. }
  755. return cubeInfo;
  756. },
  757. }
  758. }