import * as THREE from 'three'; import { animateCamera, getTextCanvas, renderVideo, drawLine } from '/@/utils/threejs/util'; import UseThree from '../../../../hooks/core/threejs/useThree'; import Fly from '/@/utils/threejs/FlyLine1'; import fcFan from './fcfanLocal.three'; import fmFan from './fmfanLocal.three'; import { types } from "util"; import num from "/@/views/demo/charts/Num.vue"; const modelName = 'jbfj_hd'; // 模型对象、 文字对象 let model, group, fcFanObj, fmFanObj, player1, fanType, flyArr = []; // 打灯光 const addLight = (scene) => { // const pointLight2 = new THREE.PointLight(0xffeeee, 1.5, 100); // pointLight2.position.set(-120, 16, -33); // pointLight2.shadow.bias = 0.05; // scene.add(pointLight2); // // const pointLight3 = new THREE.PointLight(0xffffff, 1, 40); // pointLight3.position.set(-66, 40, 1); // pointLight3.shadow.bias = 0.05; // scene.add(pointLight3); // // const pointLight4 = new THREE.PointLight(0xffeeee, 0.6, 230); // pointLight4.position.set(-18, 30, 12); // pointLight4.shadow.bias = 0.05; // scene.add(pointLight4); // // const pointLight5 = new THREE.PointLight(0xffffff, 0.8, 90); // pointLight5.position.set(-57, 7, -30); // pointLight5.shadow.bias = 0.05; // scene.add(pointLight5); // // const pointLight6 = new THREE.PointLight(0xffffff, 0.8, 270); // pointLight6.position.set(72, -33, 11.4); // pointLight6.shadow.bias = 0.05; // scene.add(pointLight6); const pointLight7 = new THREE.PointLight(0xffffff, 0.8, 500); pointLight7.position.set(-20, -43, 12); pointLight7.shadow.bias = -0.05; scene.add(pointLight7); const spotLight = new THREE.SpotLight(); spotLight.angle = Math.PI / 16; spotLight.penumbra = 0; spotLight.castShadow = true; spotLight.position.set(0, 463, 687); scene.add(spotLight); spotLight.shadow.camera.near = 0.5; // default spotLight.shadow.camera.far = 1000; // default spotLight.shadow.focus = 1; spotLight.shadow.bias = -0.000002; // gui.add(pointLight6.position, 'x', -200, 200); // gui.add(pointLight6.position, 'y', -200, 200); // gui.add(pointLight6.position, 'z', -200, 200); // gui.add(pointLight6, 'distance', 0, 500); }; // 重置摄像头 const resetCamera = () => { model.camera.position.set(0, 30, 80); model.orbitControls?.update(); model.camera.updateProjectionMatrix(); }; // 设置模型位置 const setModalPosition = () => { group.position.set(0, 18, -50); group.rotation.y = Math.PI / 2; }; // 切换局部通风机类型 export const setModelType = (type) => { fanType = type; model.camera.position.set(500, 500, 500); return new Promise((resolve) => { // 显示双道风窗 if (fanType === 'fm') { if (group.getObjectByName('jbfj_fc')) { group.remove(fcFanObj.group); } setTimeout(() => { resolve(null); const position = { x: 0, y: 0, z: 0 }; animateCamera({ x: 500, y: 500, z: 500 }, { x: 0, y: 0, z: 0 }, { x: 0, y: 30, z: 80 }, { x: position.x, y: position.y, z: position.z }, model); group.add(fmFanObj.group); }, 300); } else if (fanType === 'fc') { // 显示单道风窗 if (group.getObjectByName('jbfj_fm')) { group.remove(fmFanObj.group); } setTimeout(() => { resolve(null); const position = { x: 0, y: 0, z: 0 }; animateCamera({ x: 500, y: 500, z: 500 }, { x: 0, y: 0, z: 0 }, { x: 0, y: 30, z: 80 }, { x: position.x, y: position.y, z: position.z }, model); group.add(fcFanObj.group); }, 300); } }); }; const setControls = () => { model.orbitControls.panSpeed = 0.5; model.orbitControls.rotateSpeed = 0.5; model.orbitControls.maxPolarAngle = Math.PI / 2.4; model.orbitControls.minPolarAngle = Math.PI / 3; }; export const addFmText = (selectData) => { if (!group) { return; } const textArr = [ { text: `煤矿巷道远程风门系统`, font: 'normal 2.2rem Arial', color: '#009900', strokeStyle: '#002200', x: 80, y: 95, }, { text: `压力(Pa):`, font: 'normal 30px Arial', color: '#009900', strokeStyle: '#002200', x: 0, y: 155, }, { text: `${selectData.frontRearDP}`, font: 'normal 30px Arial', color: '#009900', strokeStyle: '#002200', x: 290, y: 155, }, { text: `动力源压力(MPa): `, font: 'normal 30px Arial', color: '#009900', strokeStyle: '#002200', x: 0, y: 215, }, { text: ` ${selectData.sourcePressure}`, font: 'normal 30px Arial', color: '#009900', strokeStyle: '#002200', x: 280, y: 215, }, { text: `故障诊断:`, font: 'normal 30px Arial', color: '#009900', strokeStyle: '#002200', x: 0, y: 275, }, { text: `${selectData.fault}`, font: 'normal 30px Arial', color: '#009900', strokeStyle: '#002200', x: 280, y: 275, }, { text: `煤炭科学技术研究院有限公司研制`, font: 'normal 28px Arial', color: '#009900', strokeStyle: '#002200', x: 20, y: 325, }, ]; getTextCanvas(526, 346, textArr, '').then((canvas) => { const textMap = track(new THREE.CanvasTexture(canvas)); // 关键一步 const textMaterial = track( new THREE.MeshBasicMaterial({ // 关于材质并未讲解 实操即可熟悉 这里是漫反射类似纸张的材质,对应的就有高光类似金属的材质. map: textMap, // 设置纹理贴图 transparent: true, side: THREE.FrontSide, // 这里是双面渲染的意思 }) ); textMaterial.blending = THREE.CustomBlending; const monitorPlane = group.getObjectByName('monitorText'); if (monitorPlane) { monitorPlane.material = textMaterial; } else { const planeGeometry = track(new THREE.PlaneGeometry(526, 346)); // 平面3维几何体PlaneGeometry const planeMesh = track(new THREE.Mesh(planeGeometry, textMaterial)); planeMesh.name = 'monitorText'; planeMesh.scale.set(0.002, 0.002, 0.002); planeMesh.position.set(-1.255, 0.09, -0.41); group.add(planeMesh); } }); }; const setFly = () => { // 路径 const curve = new THREE.CatmullRomCurve3([ // new THREE.Vector3(-90.860, 2.380, 4.854), new THREE.Vector3(-88.020, 2.360, 3.70), new THREE.Vector3(-85.872, 2.352, 3.672), new THREE.Vector3(-85.652, 2.342, 3.442), new THREE.Vector3(-85.669, 2.353, -0.002), new THREE.Vector3(-85.690, 2.367, -3.824), new THREE.Vector3(-85.650, 2.217, -4.154), new THREE.Vector3(-85.680, 1.067, -5.674), new THREE.Vector3(-85.680, 0.947, -6.024), new THREE.Vector3(-85.680, 0.947, -12.894), new THREE.Vector3(-85.450, 0.947, -12.894), new THREE.Vector3(85.000, 0.920, -12.910) ]); // 采样 for(let i = 0; i < 80; i++){ setTimeout(() => { const points: any = []; const mvPosition = { 'x' : (Math.random() * 2 - 1) * 0.01, 'y' : (Math.random() * 2 - 1) * 0.01, 'z' : (Math.random() * 2 - 1) * 0.01, } curve.getSpacedPoints(500).forEach((point) => { const { x, y, z } = point; // points.push([x + mvPosition.x, y + mvPosition.y, z + mvPosition.z]); points.push([x, y, z]); }); const length = 50; const circle = i * 2 + 8; const color = '#ffffff'; const opacity = 0.3; const size = 3; const fly = new Fly(points, length, circle, color, opacity, size); fly.move(); group.add(fly.obj); flyArr.push(fly) }, i * 500) } const stopFly = () => { flyArr.forEach((fly) => { fly.stop() }) } // 路径轨迹 const material = new THREE.LineBasicMaterial({ color: '#FFff00', }); const geometry = new THREE.BufferGeometry().setFromPoints(curve.getSpacedPoints(5000)); const line = new THREE.Line(geometry, material); model.scene.add(line); }; export const mountedThree = (playerVal1) => { player1 = playerVal1; return new Promise((resolve) => { model = new UseThree('#fanLocal3D'); model.setEnvMap('test1'); model.renderer.toneMappingExposure = 0.8; model.setModel(modelName).then(async (gltf) => { group = gltf.scene; model.scene?.add(group); if (gltf.animations && gltf.animations.length > 0) { model.mixers = []; model.animations = []; gltf.animations.forEach((animation) => { const mixer = new THREE.AnimationMixer(group); model.mixers.push(mixer); model.animations.push(animation); }); } addLight(model.scene); resetCamera(); setModalPosition(); setControls(); fcFanObj = new fcFan(model); await fcFanObj.mountedThree(); fmFanObj = new fmFan(model); await fmFanObj.mountedThree(); model.animate(); setFly(); const videoPlayer1 = document.getElementById('jb-player1')?.getElementsByClassName('vjs-tech')[0]; if (videoPlayer1) { const mesh = renderVideo(group, videoPlayer1, 'player1'); mesh.scale.set(0.222, 0.190, 0.200); mesh.position.set(-84.870, 0.298, 24.760); mesh.rotation.y = -Math.PI/2 group.add(mesh) } // const curve = new THREE.CatmullRomCurve3([ // new THREE.Vector3(-90.860, 2.380, 25.854), // new THREE.Vector3(-91.020, 2.360, 4.220), // new THREE.Vector3(-85.872, 2.352, 3.672), // new THREE.Vector3(-85.652, 2.342, 3.442), // new THREE.Vector3(-85.669, 2.353, -0.002), // new THREE.Vector3(-85.690, 2.367, -3.824), // new THREE.Vector3(-85.650, 2.217, -4.154), // new THREE.Vector3(-85.680, 1.067, -5.674), // new THREE.Vector3(-85.680, 0.947, -6.024), // new THREE.Vector3(-85.680, 0.947, -12.894), // new THREE.Vector3(-85.450, 0.947, -12.894), // new THREE.Vector3(85.000, 0.920, -12.910) // // new THREE.Vector3(76, 28, 27), // ]); // // drawLine(curve.getPoints(10), model, group) resolve(model); }); }); }; export const destroy = () => { if (model) { model.deleteModal(); model = null; group = null; } };