gate.threejs.ts 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. import * as THREE from 'three';
  2. import { CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
  3. import { getTextCanvas, renderVideo } from '/@/utils/threejs/util';
  4. import UseThree from '../../../../hooks/core/threejs/useThree';
  5. import { animateCamera } from '/@/utils/threejs/util';
  6. import { flyLine } from '/@/views/vent/comment/threejs/FlyLine';
  7. import { createComposer } from '/@/views/vent/comment/threejs/bloomPass';
  8. import * as dat from 'dat.gui';
  9. // const gui = new dat.GUI();
  10. // gui.domElement.style = 'position:absolute;top:10px;right:10px;z-index:99999999999999';
  11. const modelName = 'fm';
  12. // 模型对象、 文字对象
  13. let model, //
  14. group,
  15. fmCSS3D, //文字
  16. isLRAnimation = true, // 是否开启左右摇摆动画
  17. direction = 1, // 摇摆方向
  18. animationtimer: NodeJS.Timeout | null, // 摇摆开启定时器
  19. renderBloomPass,
  20. player1,
  21. player2,
  22. playerStartClickTime1 = new Date().getTime(),
  23. playerStartClickTime2 = new Date().getTime();
  24. const clipActionArr = {
  25. frontDoor: null as unknown as THREE.AnimationAction,
  26. backDoor: null as unknown as THREE.AnimationAction,
  27. };
  28. // 打灯光
  29. const addLight = (scene) => {
  30. const pointLight2 = new THREE.PointLight(0xffeeee, 0.8, 300);
  31. pointLight2.position.set(-113, 29, 10);
  32. // light2.castShadow = true
  33. pointLight2.shadow.bias = -0.05;
  34. scene.add(pointLight2);
  35. // const pointLightHelper2 = new THREE.PointLightHelper( pointLight2, 1 );
  36. // scene.add( pointLightHelper2 );
  37. const pointLight3 = new THREE.PointLight(0xffffff, 0.8, 100);
  38. pointLight3.position.set(0, 30, 3);
  39. // light2.castShadow = true
  40. pointLight3.shadow.bias = -0.05;
  41. scene.add(pointLight3);
  42. // const pointLightHelper = new THREE.PointLightHelper( pointLight3, 1 );
  43. // scene.add( pointLightHelper );
  44. const pointLight4 = new THREE.PointLight(0xffeeee, 0.6, 100);
  45. pointLight4.position.set(-14, 29, 13);
  46. // light2.castShadow = true
  47. pointLight4.shadow.bias = -0.05;
  48. scene.add(pointLight4);
  49. // const pointLightHelper4 = new THREE.PointLightHelper( pointLight4, 1 );
  50. // scene.add( pointLightHelper4 );
  51. const pointLight5 = new THREE.PointLight(0xffffff, 0.8, 100);
  52. pointLight5.position.set(80, 43, -5.3);
  53. // light2.castShadow = true
  54. pointLight5.shadow.bias = -0.05;
  55. scene.add(pointLight5);
  56. // const pointLightHelper5 = new THREE.PointLightHelper( pointLight5, 1 );
  57. // scene.add( pointLightHelper5 );
  58. const pointLight6 = new THREE.PointLight(0xffffff, 1, 300);
  59. // pointLight6.position.set(-47, 49, 12.9)
  60. pointLight6.position.set(-7, 40, 9);
  61. // light2.castShadow = true
  62. pointLight6.shadow.bias = -0.05;
  63. scene.add(pointLight6);
  64. // const pointLightHelper6 = new THREE.PointLightHelper( pointLight6, 1 );
  65. // scene.add( pointLightHelper6 );
  66. const pointLight7 = new THREE.PointLight(0xffffff, 0.8, 300);
  67. pointLight7.position.set(45, 51, -4.1);
  68. // light2.castShadow = true
  69. pointLight7.shadow.bias = -0.05;
  70. scene.add(pointLight7);
  71. // const pointLightHelper7 = new THREE.PointLightHelper( pointLight7, 1 );
  72. // scene.add( pointLightHelper7 );
  73. // const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
  74. // directionalLight.target = group;
  75. // directionalLight.position.set(-18, 20, 39);
  76. // directionalLight.rotation.set(1.3, 0.3, 5.8);
  77. // scene.add(directionalLight);
  78. // const helper = new THREE.DirectionalLightHelper(directionalLight, 5);
  79. // scene.add(helper);
  80. const spotLight = new THREE.SpotLight();
  81. spotLight.angle = Math.PI / 16;
  82. spotLight.penumbra = 0;
  83. // spotLight.castShadow = true;
  84. spotLight.position.set(-231, 463, 687);
  85. scene.add(spotLight);
  86. // spotLight.shadow.mapSize.width = 1500; // default
  87. // spotLight.shadow.mapSize.height = 800; // default
  88. spotLight.shadow.camera.near = 0.5; // default
  89. spotLight.shadow.camera.far = 1000; // default
  90. spotLight.shadow.focus = 1.2;
  91. spotLight.shadow.bias = -0.000002;
  92. // const spotLightHelper = new THREE.SpotLightHelper(spotLight);
  93. // scene.add(spotLightHelper);
  94. // model.canvasContainer?.appendChild(gui.domElement);
  95. // gui.add(directionalLight.position, 'x', -100, 100).step(1);
  96. // gui.add(directionalLight.position, 'y', -100, 100).step(1);
  97. // gui.add(directionalLight.position, 'z', -100, 100).step(1);
  98. // gui.add(directionalLight.rotation, 'x', -Math.PI, 2 * Math.PI).step(0.1);
  99. // gui.add(directionalLight.rotation, 'y', -Math.PI, 2 * Math.PI).step(0.1);
  100. // gui.add(directionalLight.rotation, 'z', -Math.PI, 2 * Math.PI).step(0.1);
  101. // gui.add(spotLight, 'angle', 0, Math.PI / 2);
  102. // gui.add(spotLight, 'distance', 0, 1000);
  103. // gui.add(pointLight6.position, 'x', -200, 200)
  104. // gui.add(pointLight6.position, 'y', -200, 200)
  105. // gui.add(pointLight6.position, 'z', -200, 200)
  106. };
  107. // 重置摄像头
  108. const resetCamera = () => {
  109. model.camera.far = 274;
  110. model.orbitControls?.update();
  111. model.camera.updateProjectionMatrix();
  112. };
  113. // 设置模型位置
  114. const setModalPosition = () => {
  115. group?.scale.set(22, 22, 22);
  116. group.position.set(-20, 20, 9);
  117. };
  118. // // css3D文字
  119. // const addFm1Text = () => {
  120. // fmCSS3D = new CSS3DObject(elementContent.value);
  121. // fmCSS3D.scale.set(0.13, 0.13, 0.13);
  122. // fmCSS3D.position.set(0, 52, 0);
  123. // fmCSS3D.lookAt(model.camera.position.clone());
  124. // model?.scene.add(fmCSS3D);
  125. // };
  126. /* 添加监控数据 */
  127. export const addFmText = (selectData) => {
  128. if (!group) {
  129. return;
  130. }
  131. const textArr = [
  132. {
  133. text: `煤矿巷道远程风门系统`,
  134. font: 'normal 2.2rem Arial',
  135. color: '#009900',
  136. strokeStyle: '#002200',
  137. x: 80,
  138. y: 95,
  139. },
  140. {
  141. text: `压力(Pa):`,
  142. font: 'normal 30px Arial',
  143. color: '#009900',
  144. strokeStyle: '#002200',
  145. x: 0,
  146. y: 155,
  147. },
  148. {
  149. text: `${selectData.frontRearDP}`,
  150. font: 'normal 30px Arial',
  151. color: '#009900',
  152. strokeStyle: '#002200',
  153. x: 290,
  154. y: 155,
  155. },
  156. {
  157. text: `动力源压力(MPa): `,
  158. font: 'normal 30px Arial',
  159. color: '#009900',
  160. strokeStyle: '#002200',
  161. x: 0,
  162. y: 215,
  163. },
  164. {
  165. text: ` ${selectData.sourcePressure}`,
  166. font: 'normal 30px Arial',
  167. color: '#009900',
  168. strokeStyle: '#002200',
  169. x: 280,
  170. y: 215,
  171. },
  172. {
  173. text: `故障诊断:`,
  174. font: 'normal 30px Arial',
  175. color: '#009900',
  176. strokeStyle: '#002200',
  177. x: 0,
  178. y: 275,
  179. },
  180. {
  181. text: `${selectData.fault}`,
  182. font: 'normal 30px Arial',
  183. color: '#009900',
  184. strokeStyle: '#002200',
  185. x: 280,
  186. y: 275,
  187. },
  188. {
  189. text: `煤炭科学技术研究院有限公司研制`,
  190. font: 'normal 28px Arial',
  191. color: '#009900',
  192. strokeStyle: '#002200',
  193. x: 20,
  194. y: 325,
  195. },
  196. ];
  197. //
  198. getTextCanvas(526, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
  199. const textMap = new THREE.CanvasTexture(canvas); // 关键一步
  200. const textMaterial = new THREE.MeshBasicMaterial({
  201. // 关于材质并未讲解 实操即可熟悉 这里是漫反射类似纸张的材质,对应的就有高光类似金属的材质.
  202. map: textMap, // 设置纹理贴图
  203. transparent: true,
  204. side: THREE.FrontSide, // 这里是双面渲染的意思
  205. });
  206. textMaterial.blending = THREE.CustomBlending;
  207. const monitorPlane = group.getObjectByName('monitorText');
  208. if (monitorPlane) {
  209. monitorPlane.material = textMaterial;
  210. } else {
  211. const planeGeometry = new THREE.PlaneGeometry(526, 346); // 平面3维几何体PlaneGeometry
  212. const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
  213. planeMesh.name = 'monitorText';
  214. planeMesh.scale.set(0.002, 0.002, 0.002);
  215. planeMesh.position.set(-1.255, 0.09, -0.41);
  216. group.add(planeMesh);
  217. }
  218. });
  219. };
  220. /* 漫游路线 */
  221. const createLine = () => {
  222. const position = model.camera.position.clone();
  223. //创建样条曲线,作为运动轨迹
  224. const curve = new THREE.CatmullRomCurve3([
  225. new THREE.Vector3(position.x, position.y, position.z),
  226. new THREE.Vector3(26.586, 17.86, 14.144),
  227. new THREE.Vector3(-0.075, 19.669, 15.051),
  228. new THREE.Vector3(-154.882, 17.462, 14.981),
  229. // new THREE.Vector3(76, 28, 27),
  230. ]);
  231. const geometry = new THREE.BufferGeometry().setFromPoints(curve.getPoints(5000));
  232. // 材质对象
  233. const material = new THREE.LineBasicMaterial({
  234. color: 'red',
  235. });
  236. // 线条模型对象
  237. const line = new THREE.Line(geometry, material);
  238. // model?.scene.add(line) // 线条对象添加到场景中
  239. return curve;
  240. };
  241. /* 开启漫游 */
  242. const enterMY = () => {
  243. model.startAnimation = () => {};
  244. model.camera.position.set(114.27, 15.293, 14.189);
  245. model.camera.rotation.set(-86.23, 69.89, 85.98);
  246. const curve = createLine();
  247. let progress = 0;
  248. model.startMY = () => {
  249. if (progress <= 1 - 0.004 * 20) {
  250. const point = curve.getPointAt(progress); //获取样条曲线指定点坐标,作为相机的位置
  251. const pointBox = curve.getPointAt(progress + 0.004 * 20); //获取样条曲线指定点坐标
  252. model.camera.position.set(point.x, point.y, point.z);
  253. model.camera.lookAt(pointBox.x + 5, pointBox.y, pointBox.z);
  254. // model.orbitControls.position0.set(point.x, point.y, point.z) //非必要,场景有控件时才加上
  255. // model.orbitControls.target.set(pointBox.x, pointBox.y , pointBox.z) //非必要,场景有控件时才加上
  256. progress += 0.004;
  257. } else {
  258. // progress = 0
  259. model.camera.position.set(30.328, 58.993, 148.315);
  260. model.camera.rotation.set(-27.88, 14.35, 7.47);
  261. model.camera.lookAt(0, 0, 0);
  262. model.startMY = () => {};
  263. model.startAnimation = fmAnimation.bind(null);
  264. }
  265. };
  266. };
  267. /* 风门动画 */
  268. const render = () => {
  269. if (!model) {
  270. return;
  271. }
  272. if (isLRAnimation && group) {
  273. // 左右摇摆动画
  274. if (Math.abs(group.rotation.y) >= 0.2) {
  275. direction = -direction;
  276. group.rotation.y += 0.00002 * 30 * direction;
  277. } else {
  278. group.rotation.y += 0.00002 * 30 * direction;
  279. }
  280. }
  281. // // //自发光
  282. // const screen = group.getObjectByName('对象156');
  283. // if (screen) {
  284. // model.renderer.clearDepth();
  285. // screen.layers.enable(31);
  286. // !!renderBloomPass && renderBloomPass(group);
  287. // }
  288. // 风门开关动画
  289. const delta = model.clock?.getElapsedTime();
  290. if (model.mixers[0]) model.mixers[0]?.update(delta);
  291. };
  292. // 鼠标点击、松开事件
  293. const mouseEvent = (event) => {
  294. event.stopPropagation();
  295. // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
  296. model.mouse.x = ((event.clientX - model.canvasContainer.getBoundingClientRect().left) / model.canvasContainer.clientWidth) * 2 - 1;
  297. model.mouse.y = -((event.clientY - model.canvasContainer.getBoundingClientRect().top) / model.canvasContainer.clientHeight) * 2 + 1;
  298. (model.rayCaster as THREE.Raycaster).setFromCamera(model.mouse, model.camera as THREE.Camera);
  299. // 计算物体和射线的焦点
  300. const intersects = model.rayCaster?.intersectObjects(group.children) as THREE.Intersection[];
  301. if (intersects.length > 0) {
  302. isLRAnimation = false;
  303. if (animationtimer) {
  304. clearTimeout(animationtimer);
  305. animationtimer = null;
  306. }
  307. // 判断是否点击到视频
  308. intersects.find((intersect) => {
  309. const mesh = intersect.object;
  310. if (mesh.name === 'player1') {
  311. if (new Date().getTime() - playerStartClickTime1 < 400) {
  312. // model.orbitControls?.dispatchEvent.call(model.orbitControls, { type: 'end' })
  313. // 双击,视频放大
  314. if (player1) {
  315. player1.requestFullscreen();
  316. }
  317. }
  318. playerStartClickTime1 = new Date().getTime();
  319. return true;
  320. } else if (mesh.name === 'player2') {
  321. if (new Date().getTime() - playerStartClickTime2 < 400) {
  322. // model.orbitControls?.dispatchEvent.call(model.orbitControls, { type: 'end' })
  323. // 双击,视频放大
  324. if (player2) {
  325. player2.requestFullscreen();
  326. }
  327. }
  328. playerStartClickTime2 = new Date().getTime();
  329. return true;
  330. }
  331. return false;
  332. });
  333. }
  334. };
  335. // 初始化左右摇摆动画
  336. const startAnimation = () => {
  337. // 开启动画
  338. model.startAnimation = render.bind(null);
  339. // 定义鼠标点击事件x
  340. model.canvasContainer?.addEventListener('pointerdown', mouseEvent.bind(null));
  341. model.canvasContainer?.addEventListener('pointerup', (event) => {
  342. event.stopPropagation();
  343. // 10s后开始摆动
  344. if (!animationtimer && !isLRAnimation) {
  345. animationtimer = setTimeout(() => {
  346. isLRAnimation = true;
  347. }, 10000);
  348. }
  349. });
  350. };
  351. /* 提取风门序列帧,初始化前后门动画 */
  352. const initAnimation = () => {
  353. const tracks = model.animations[0].tracks;
  354. const fontTracks: any[] = [],
  355. backTracks: any[] = [];
  356. for (let i = 0; i < tracks.length; i++) {
  357. const track = tracks[i];
  358. if (track.name.startsWith('qianmen')) {
  359. fontTracks.push(track);
  360. } else if (track.name.startsWith('houmen')) {
  361. backTracks.push(track);
  362. }
  363. }
  364. const frontDoor = new THREE.AnimationClip('frontDoor', 4, fontTracks);
  365. const backDoor = new THREE.AnimationClip('backDoor', 4, backTracks);
  366. const arr = [frontDoor, backDoor];
  367. arr.forEach((animationClip) => {
  368. const clipAction = model.mixers[0].clipAction(animationClip, group);
  369. clipAction.clampWhenFinished = true;
  370. clipAction.loop = THREE.LoopOnce;
  371. if (animationClip.name == 'frontDoor') clipActionArr.frontDoor = clipAction;
  372. if (animationClip.name == 'backDoor') clipActionArr.backDoor = clipAction;
  373. });
  374. };
  375. // 播放动画
  376. export const play = (handlerState) => {
  377. let handler = () => {};
  378. switch (handlerState) {
  379. case 1: // 打开前门
  380. handler = () => {
  381. clipActionArr.frontDoor.paused = true;
  382. clipActionArr.frontDoor.reset();
  383. clipActionArr.frontDoor.time = 0.5;
  384. clipActionArr.frontDoor.timeScale = 0.01;
  385. clipActionArr.frontDoor.clampWhenFinished = true;
  386. clipActionArr.frontDoor.play();
  387. };
  388. break;
  389. case 2: // 关闭前门
  390. handler = () => {
  391. clipActionArr.frontDoor.paused = true;
  392. clipActionArr.frontDoor.reset(); //
  393. clipActionArr.frontDoor.time = 4;
  394. clipActionArr.frontDoor.timeScale = -0.01;
  395. clipActionArr.frontDoor.clampWhenFinished = true;
  396. clipActionArr.frontDoor.play();
  397. };
  398. break;
  399. case 3: // 打开后门
  400. handler = () => {
  401. clipActionArr.backDoor.paused = true;
  402. clipActionArr.backDoor.reset();
  403. clipActionArr.backDoor.time = 0.5;
  404. clipActionArr.backDoor.timeScale = 0.01;
  405. clipActionArr.backDoor.clampWhenFinished = true;
  406. clipActionArr.backDoor.play();
  407. };
  408. break;
  409. case 4: // 关闭后门
  410. handler = () => {
  411. clipActionArr.backDoor.paused = true;
  412. clipActionArr.backDoor.reset();
  413. clipActionArr.backDoor.time = 4;
  414. clipActionArr.backDoor.timeScale = -0.01;
  415. clipActionArr.backDoor.clampWhenFinished = true;
  416. clipActionArr.backDoor.play();
  417. };
  418. break;
  419. case 5: // 打开前后门
  420. handler = () => {
  421. clipActionArr.backDoor.paused = true;
  422. clipActionArr.frontDoor.paused = true;
  423. clipActionArr.frontDoor.reset();
  424. clipActionArr.frontDoor.time = 0.5;
  425. clipActionArr.frontDoor.timeScale = 0.01;
  426. clipActionArr.frontDoor.clampWhenFinished = true;
  427. clipActionArr.frontDoor.play();
  428. clipActionArr.backDoor.reset();
  429. clipActionArr.backDoor.time = 0.5;
  430. clipActionArr.backDoor.timeScale = 0.01;
  431. clipActionArr.backDoor.clampWhenFinished = true;
  432. clipActionArr.backDoor.play();
  433. };
  434. break;
  435. case 6: // 关闭前后门
  436. handler = () => {
  437. clipActionArr.backDoor.paused = true;
  438. clipActionArr.frontDoor.paused = true;
  439. clipActionArr.frontDoor.reset();
  440. clipActionArr.frontDoor.time = 4;
  441. clipActionArr.frontDoor.timeScale = -0.01;
  442. clipActionArr.frontDoor.clampWhenFinished = true;
  443. clipActionArr.frontDoor.play();
  444. clipActionArr.backDoor.reset();
  445. clipActionArr.backDoor.time = 4;
  446. clipActionArr.backDoor.timeScale = -0.01;
  447. clipActionArr.backDoor.clampWhenFinished = true;
  448. clipActionArr.backDoor.play();
  449. };
  450. break;
  451. default:
  452. }
  453. handler();
  454. model.clock.start();
  455. // const honglvdeng = group.getObjectByName('honglvdeng');
  456. // const material = honglvdeng.material;
  457. // setTimeout(() => {
  458. // if (handlerState === 2 || handlerState === 4 || handlerState === 6) {
  459. // material.color = new THREE.Color(0x00ff00);
  460. // } else {
  461. // material.color = new THREE.Color(0xff0000);
  462. // }
  463. // }, 1000);
  464. };
  465. // 初始化门的开关状态
  466. export const initOpenState = (selectData) => {
  467. if (!group) return;
  468. model.camera.position.set(-1000, 100, 500);
  469. group.rotation.y = 0;
  470. return new Promise((resolve) => {
  471. setTimeout(async () => {
  472. const oldCameraPosition = { x: -1000, y: 100, z: 500 };
  473. await animateCamera(oldCameraPosition, oldCameraPosition, { x: 46.257, y: 57.539, z: 94.313 }, { x: -50, y: 0, z: 0 }, model, 0.8);
  474. resolve(null);
  475. }, 500);
  476. if (!selectData) {
  477. return;
  478. }
  479. if (selectData.frontGateOpen == 1) {
  480. clipActionArr.frontDoor.reset();
  481. clipActionArr.frontDoor.time = 0.5;
  482. clipActionArr.frontDoor.clampWhenFinished = true;
  483. clipActionArr.frontDoor.timeScale = 1;
  484. clipActionArr.frontDoor.play();
  485. } else {
  486. clipActionArr.frontDoor.reset();
  487. clipActionArr.frontDoor.time = 4;
  488. clipActionArr.frontDoor.timeScale = -1;
  489. clipActionArr.frontDoor.clampWhenFinished = true;
  490. clipActionArr.frontDoor.play();
  491. }
  492. if (selectData.rearGateOpen == 1) {
  493. clipActionArr.backDoor.reset();
  494. clipActionArr.backDoor.time = 0.5;
  495. clipActionArr.backDoor.timeScale = 1;
  496. clipActionArr.backDoor.clampWhenFinished = true;
  497. clipActionArr.backDoor.play();
  498. } else {
  499. clipActionArr.backDoor.reset();
  500. clipActionArr.backDoor.time = 4;
  501. clipActionArr.backDoor.timeScale = -1;
  502. clipActionArr.backDoor.clampWhenFinished = true;
  503. clipActionArr.backDoor.play();
  504. }
  505. model.clock.start();
  506. });
  507. };
  508. export const mountedThree = (playerVal1, playerVal2) => {
  509. return new Promise((resolve) => {
  510. model = new UseThree('#damper3D');
  511. model.setEnvMap('test1');
  512. model.renderer.toneMappingExposure = 0.8;
  513. model.setModel(modelName).then((gltf) => {
  514. group = gltf.scene;
  515. if (gltf.animations && gltf.animations.length > 0) {
  516. model.mixers = [];
  517. model.animations = [];
  518. gltf.animations.forEach((animation) => {
  519. const mixer = new THREE.AnimationMixer(group);
  520. model.mixers.push(mixer);
  521. model.animations.push(animation);
  522. });
  523. }
  524. model.scene?.add(group);
  525. // model.camera.position.set(-1000, 100, 500);
  526. addLight(model.scene);
  527. // resetCamera();
  528. setModalPosition();
  529. startAnimation();
  530. // 初始化左右摇摆动画;
  531. // startAnimation();
  532. initAnimation();
  533. model.animate();
  534. // renderBloomPass = createComposer(model).renderBloomPass;
  535. // const flyLineMesh = flyLine(
  536. // [
  537. // new THREE.Vector3(-110, 0, 0),
  538. // // new THREE.Vector3(5, 4, 0),
  539. // new THREE.Vector3(120, 0, 0),
  540. // ],
  541. // '/model/hdr/y1.png'
  542. // );
  543. // group.add(flyLineMesh);
  544. setTimeout(async () => {
  545. player1 = playerVal1;
  546. player2 = playerVal2;
  547. const videoPlayer1 = document.getElementById('fm-player1')?.getElementsByClassName('vjs-tech')[0];
  548. const videoPlayer2 = document.getElementById('fm-player2')?.getElementsByClassName('vjs-tech')[0];
  549. if (videoPlayer1) {
  550. const mesh = renderVideo(group, videoPlayer1, 'player1');
  551. mesh.scale.set(-0.028, 0.0285, 1);
  552. mesh.position.set(4.298, 0.02, -0.4);
  553. mesh.rotation.y = -Math.PI;
  554. group.add(mesh);
  555. }
  556. if (videoPlayer2) {
  557. const mesh = renderVideo(group, videoPlayer2, 'player2');
  558. mesh.scale.set(-0.028, 0.0285, 1);
  559. mesh.position.set(-4.262, 0.02, -0.4);
  560. mesh.rotation.y = -Math.PI;
  561. group.add(mesh);
  562. }
  563. resolve(model);
  564. }, 0);
  565. });
  566. });
  567. };
  568. export const destroy = () => {
  569. if (model) {
  570. if (model.mixers[0]) {
  571. model.mixers[0].uncacheClip(clipActionArr.frontDoor.getClip());
  572. model.mixers[0].uncacheClip(clipActionArr.backDoor.getClip());
  573. model.mixers[0].uncacheAction(clipActionArr.frontDoor, group);
  574. model.mixers[0].uncacheAction(clipActionArr.backDoor, group);
  575. model.mixers[0].uncacheRoot(group);
  576. model.animations[0].tracks = [];
  577. }
  578. clipActionArr.backDoor = undefined;
  579. clipActionArr.frontDoor = undefined;
  580. model.mixers = [];
  581. model.deleteModal();
  582. model = null;
  583. group = null;
  584. // document.getElementById('damper3D').parentElement.remove(document.getElementById('damper3D'))
  585. }
  586. };