import * as THREE from 'three'; import UseThree from '../../../../utils/threejs/useThree'; import singleWindow from './dandaoFc.threejs'; import doubleWindow from './shuangdaoFc.threejs'; import { animateCamera } from '/@/utils/threejs/util'; import { useAppStore } from '/@/store/modules/app'; // 模型对象、 文字对象 let model, singleWindowObj, doubleWindowObj, group, windowType = 'singleWindow'; const appStore = useAppStore(); // 打灯光 const addLight = () => { const pointLight2 = new THREE.PointLight(0xffeeee, 1, 83); pointLight2.position.set(-101, 34, 16); pointLight2.shadow.bias = 0.05; model.scene.add(pointLight2); const pointLight3 = new THREE.PointLight(0xffffff, 1, 150); pointLight3.position.set(-61, 37, 13.9); pointLight3.shadow.bias = 0.05; model.scene.add(pointLight3); const pointLight4 = new THREE.PointLight(0xffeeee, 0.6, 300); pointLight4.position.set(-2, 26, 20); pointLight4.shadow.bias = 0.05; model.scene.add(pointLight4); const pointLight5 = new THREE.PointLight(0xffffff, 0.8, 120); pointLight5.position.set(-54, 30, 23.8); pointLight5.shadow.bias = 0.05; model.scene.add(pointLight5); const pointLight7 = new THREE.PointLight(0xffffff, 1, 1000); pointLight7.position.set(45, 51, -4.1); pointLight7.shadow.bias = 0.05; model.scene.add(pointLight7); const spotLight = new THREE.SpotLight(); spotLight.angle = Math.PI / 16; spotLight.penumbra = 0; spotLight.castShadow = true; spotLight.intensity = 1; spotLight.position.set(-231, 463, 687); model.scene.add(spotLight); spotLight.shadow.camera.near = 0.5; // default spotLight.shadow.camera.far = 1000; // default spotLight.shadow.focus = 1.2; spotLight.shadow.bias = -0.000002; }; // // 重置摄像头 // const resetCamera = () => { // model.camera.position.set(30.328, 58.993, 148.315); // model.camera.rotation.set(-31.85, 30.07, 17.29); // model.orbitControls?.update(); // model.camera.updateProjectionMatrix(); // }; // 初始化左右摇摆动画 const startAnimation = () => { // 定义鼠标点击事件 model.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null)); model.canvasContainer?.addEventListener('pointerup', (event) => { event.stopPropagation(); // 单道、 双道 if (windowType === 'doubleWindow') { doubleWindowObj.mouseUpModel.call(doubleWindowObj); } else if (windowType === 'singleWindow') { singleWindowObj.mouseUpModel.call(singleWindowObj); } }); }; // 鼠标点击、松开事件 const mouseEvent = (event) => { event.stopPropagation(); const widthScale = appStore.getWidthScale; const heightScale = appStore.getHeightScale; // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1) model.mouse.x = ((-model.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (model.canvasContainer.clientWidth * widthScale)) * 2 - 1; model.mouse.y = -((-model.canvasContainer.getBoundingClientRect().top + event.clientY) / (model.canvasContainer.clientHeight * heightScale)) * 2 + 1; (model.rayCaster as THREE.Raycaster).setFromCamera(model.mouse, model.camera as THREE.Camera); if (group) { const intersects = model.rayCaster?.intersectObjects(group.children, false) as THREE.Intersection[]; if (intersects.length > 0) { // 单道、 双道 if (windowType === 'doubleWindow') { doubleWindowObj.mousedownModel.call(doubleWindowObj, intersects); } else if (windowType === 'singleWindow') { singleWindowObj.mousedownModel.call(singleWindowObj, intersects); } } } }; export const addFmText = (selectData) => { if (windowType === 'doubleWindow') { return doubleWindowObj.addFmText.call(doubleWindowObj, selectData); } else { return singleWindowObj.addFmText.call(singleWindowObj, selectData); } }; export const play = (rotationParam, flag) => { if (windowType === 'doubleWindow') { return doubleWindowObj.play.call(doubleWindowObj, rotationParam, flag); } else { return singleWindowObj.play.call(singleWindowObj, rotationParam, flag); } }; // 切换风窗类型 export const setModelType = (type) => { windowType = type; return new Promise((resolve) => { // 显示双道风窗 if (windowType === 'doubleWindow') { model.startAnimation = doubleWindowObj.render.bind(doubleWindowObj); group = doubleWindowObj.group; if (model.scene.getObjectByName('ddFc')) { model.scene.remove(singleWindowObj.group); } const oldCameraPosition = { x: 100, y: 0, z: 500 }; model.scene.add(doubleWindowObj.group); setTimeout(async () => { resolve(null); const position = doubleWindowObj.group; await animateCamera( oldCameraPosition, oldCameraPosition, { x: 66.257, y: 57.539, z: 94.313 }, { x: position.x, y: position.y, z: position.z }, model ); }, 300); } else if (windowType === 'singleWindow') { // 显示单道风窗 model.startAnimation = singleWindowObj.render.bind(singleWindowObj); group = singleWindowObj.group; if (model.scene.getObjectByName('sdFc')) { model.scene.remove(doubleWindowObj.group); } const oldCameraPosition = { x: 100, y: 0, z: 500 }; model.scene.add(singleWindowObj.group); setTimeout(async () => { resolve(null); const position = { x: 0, y: 0, z: 0 }; await animateCamera( oldCameraPosition, { x: 0, y: 0, z: 0 }, { x: 66.257, y: 57.539, z: 94.313 }, { x: position.x, y: position.y, z: position.z }, model ); }, 300); } }); }; export const mountedThree = (playerVal1, playerVal2) => { return new Promise(async (resolve) => { model = new UseThree('#window3D'); model.setEnvMap('test1'); model.renderer.toneMappingExposure = 0.8; model.camera.position.set(100, 0, 1000); // 单道、 双道 doubleWindowObj = new doubleWindow(model, playerVal1, playerVal2); singleWindowObj = new singleWindow(model, playerVal1); await doubleWindowObj.mountedThree(); await singleWindowObj.mountedThree(); model.animate(); resolve(null); addLight(); startAnimation(); }); }; export const destroy = () => { if (model) { doubleWindowObj.destroy(); singleWindowObj.destroy(); model.deleteModal(); model = null; group = null; singleWindowObj = null; doubleWindowObj = null; } };