import * as THREE from 'three'; import { setModalCenter } from '/@/utils/threejs/util'; import { CSS3DSprite } from 'three/examples/jsm/renderers/CSS3DRenderer.js'; import { CSS3DRenderer } from 'three/examples/jsm/renderers/CSS3DRenderer.js'; // import * as dat from 'dat.gui'; // const gui = new dat.GUI(); // gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999'; class Nitrogen { model; modelName = 'compressor'; group: THREE.Object3D = new THREE.Object3D(); animationTimer; isLRAnimation = true; direction = 1; playerStartClickTime1 = new Date().getTime(); playerStartClickTime2 = new Date().getTime(); deviceRunState = ''; nitrogenNum = 0; singGltf: THREE.Object3D | undefined = undefined; CSSCanvasContainer; css3dRender; canvasContainer; cssGroupParent: THREE.Group = new THREE.Group(); constructor(model) { this.model = model; this.group.name = this.modelName; } addLight() { const directionalLight = new THREE.DirectionalLight(0xffffff, 1); directionalLight.position.set(141, 259, 121); this.group.add(directionalLight); directionalLight.target = this.group; // gui.add(directionalLight.position, 'x', -100, 200).onChange(function (value) { // directionalLight.position.x = Number(value); // }); // gui.add(directionalLight.position, 'y', -500, 500).onChange(function (value) { // directionalLight.position.y = Number(value); // }); // gui.add(directionalLight.position, 'z', -200, 200).onChange(function (value) { // directionalLight.position.z = Number(value); // }); // const spotLight = new THREE.SpotLight(); // spotLight.angle = Math.PI / 4; // spotLight.penumbra = 0; // spotLight.castShadow = true; // spotLight.distance = 0; // spotLight.position.set(-36, 68, 189); // spotLight.target = this.group; // this.group.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(spotLight.position, 'x', -800, 800).onChange(function (value) { // spotLight.position.x = Number(value); // }); // gui.add(spotLight.position, 'y', -800, 800).onChange(function (value) { // spotLight.position.y = Number(value); // }); // gui.add(spotLight.position, 'z', -800, 800).onChange(function (value) { // spotLight.position.z = Number(value); // }); } // 设置模型位置 setModalPosition() { this.group.position.set(0, 0, 0); this.group?.scale.set(24.0, 24.0, 24.0); // if (this.nitrogenNum == 4) { // this.group.position.set(0, -17, 3); // } // if (this.nitrogenNum == 3) { // this.group.position.set(0, -12, 3); // } // if (this.nitrogenNum == 2) { // this.group.position.set(0, 0.42, 1.21); // } // if (this.nitrogenNum == 1) { // this.group.position.set(0, 8, 3.0); // } } /* 提取风门序列帧,初始化前后门动画 */ initAnimation() {} /* 点击 */ mousedownModel(intersects: THREE.Intersection>[]) { this.isLRAnimation = false; if (this.animationTimer) { clearTimeout(this.animationTimer); this.animationTimer = null; } intersects.find((intersect) => { const mesh = intersect.object; return false; }); } mouseUpModel() {} // 播放动画 play() {} /** * 生序排列模型的子元素 */ sortMeshChildren = (children: THREE.Mesh[]) => { //生序排列 children.sort((x, y) => { return x.geometry.attributes.position.count - y.geometry.attributes.position.count; }); return children; }; /** * 设置模型透明 */ transparentModel = (model: THREE.Mesh) => { const transparentMaterial = new THREE.MeshBasicMaterial({ transparent: true, opacity: 0, }); model.material = transparentMaterial; }; addCssText = (monitorDataGroup) => { if (this.nitrogenNum > 0 && this.group) { for (let i = 0; i < monitorDataGroup.length; i++) { const n = monitorDataGroup[i]; const compressorModal = this.group.getObjectByName('compressorModal' + i) as THREE.Object3D; const compressorGroup = this.cssGroupParent.getObjectByName('compressorGroup' + n); if (!compressorGroup) { const cssGroup = new THREE.Object3D(); cssGroup.name = 'compressorGroup' + n; cssGroup.applyMatrix4(compressorModal.matrixWorld); const compressorElement = document.getElementById('nitrogenMonitor' + n) as HTMLElement; if (compressorElement) { compressorElement.style.top = '0px'; compressorElement.style.left = '0px'; const compressorMonitorCSS3D = new CSS3DSprite(compressorElement); compressorMonitorCSS3D.name = 'monitorNitrogenText' + n; compressorMonitorCSS3D.scale.set(0.003, 0.003, 0.003); if (i == 0) compressorMonitorCSS3D.position.set(-0.89, 0.31, 0); if (i == 1) compressorMonitorCSS3D.position.set(-0.89, 0.31, 0.04); if (i == 2) compressorMonitorCSS3D.position.set(-0.89, 0.31, 0.08); if (i == 3) compressorMonitorCSS3D.position.set(-0.89, 0.31, 0.12); cssGroup.add(compressorMonitorCSS3D); } const cqgElement = document.getElementById('cqgMonitor' + n) as HTMLElement; if (cqgElement) { cqgElement.style.top = '0px'; cqgElement.style.left = '0px'; const cqgMonitorCSS3D = new CSS3DSprite(cqgElement); cqgMonitorCSS3D.name = 'cqgMonitorText' + n; cqgMonitorCSS3D.scale.set(0.003, 0.003, 0.003); if (i == 0) cqgMonitorCSS3D.position.set(1.24, 0.31, 0.0); if (i == 1) cqgMonitorCSS3D.position.set(1.24, 0.31, 0.04); if (i == 2) cqgMonitorCSS3D.position.set(1.24, 0.31, 0.08); if (i == 3) cqgMonitorCSS3D.position.set(1.24, 0.31, 0.12); cssGroup.add(cqgMonitorCSS3D); } this.cssGroupParent.add(cssGroup); } else { } } } }; clearCssText = () => { for (let i = 0; i < this.cssGroupParent.children.length; i++) { const item = this.cssGroupParent.children[i]; this.cssGroupParent.remove(item); } }; /** * 处理杯子的纹理和杯子外层透明壳子 */ handleGlassAndWrap = ( objects: THREE.Object3D, withVolume: THREE.Object3D[], glassModel: THREE.Mesh, params: THREE.MeshPhysicalMaterialParameters, scale: number, position: THREE.Vector3, rotation?: THREE.Vector3 ) => { //辨别杯子和壳 大的是杯子 小的是壳 壳的点比杯子少 const children = glassModel.children as THREE.Mesh[]; this.sortMeshChildren(children); children.forEach((mesh) => { mesh.position.copy(position); mesh.scale.set(scale, scale, scale); rotation && mesh.rotation.setFromVector3(rotation, 'XYZ'); }); const [transparentWrap, glass] = children; this.transparentModel(transparentWrap); glass.material = new THREE.MeshPhysicalMaterial({ side: THREE.DoubleSide, // specularColor: new Color("#ffffff"), // color: new Color(0xffa000), ...params, }); objects.add(...children); //只检测壳子 减小开销 withVolume.push(transparentWrap); }; setModal(nitrogenNum) { if (nitrogenNum < 1) { return; } if (this.singGltf) { this.nitrogenNum = nitrogenNum; const nitrogenGroup = new THREE.Object3D(); const flag = nitrogenNum % 2 == 0 ? 0 : 1; for (let i = 0; i < nitrogenNum; i++) { const compressorModal = this.singGltf?.clone(); compressorModal.name = 'compressorModal' + i; const c = Math.floor(nitrogenNum / 2); if (flag) { compressorModal.position.set(0, 0, 1.29 * (c - i)); } else { compressorModal.position.set(0, 0, (c - i - 0.5) * 1.29); } nitrogenGroup.add(compressorModal); } this.group = nitrogenGroup; this.group.name = this.modelName; setModalCenter(this.group); this.setModalPosition(); } } mountedThree(monitorDataGroup, dom) { return new Promise((resolve) => { this.CSSCanvasContainer = document.querySelector(dom); if (this.CSSCanvasContainer) { this.css3dRender = new CSS3DRenderer() as CSS3DRenderer; this.css3dRender.setSize(this.model.canvasContainer.clientWidth, this.model.canvasContainer.clientHeight); this.CSSCanvasContainer?.appendChild(this.css3dRender.domElement); } this.model.setGLTFModel([this.modelName]).then(async (gltf) => { this.singGltf = gltf[0]; this.setModal(monitorDataGroup.length); this.addCssText(monitorDataGroup); // this.addLight(); this.group.add(this.cssGroupParent); resolve(null); }); }); } destroy() { if (this.group) { this.model.clearGroup(this.group); } this.model = null; this.group = null; } } export default Nitrogen;