|
@@ -0,0 +1,404 @@
|
|
|
+import * as THREE from 'three';
|
|
|
+import { getTextCanvas, addEnvMap } from '/@/utils/threejs/util';
|
|
|
+
|
|
|
+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 = 'nitrogen';
|
|
|
+ // modelName = 'glass';
|
|
|
+ group: THREE.Object3D = new THREE.Object3D();
|
|
|
+ animationTimer;
|
|
|
+ isLRAnimation = true;
|
|
|
+ direction = 1;
|
|
|
+ playerStartClickTime1 = new Date().getTime();
|
|
|
+ playerStartClickTime2 = new Date().getTime();
|
|
|
+ deviceRunState = '';
|
|
|
+
|
|
|
+ constructor(model) {
|
|
|
+ this.model = model;
|
|
|
+ this.group.name = this.modelName;
|
|
|
+ }
|
|
|
+
|
|
|
+ addLight() {
|
|
|
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
|
|
|
+ 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?.scale.set(22, 22, 22);
|
|
|
+ this.group?.position.set(-25, 25, 15);
|
|
|
+ }
|
|
|
+
|
|
|
+ addText(selectData) {
|
|
|
+ if (!this.group) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const textArr = [
|
|
|
+ {
|
|
|
+ text: `龙门式测风装置`,
|
|
|
+ font: 'normal 32px Arial',
|
|
|
+ color: '#009900',
|
|
|
+ strokeStyle: '#002200',
|
|
|
+ x: 170,
|
|
|
+ y: 40,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: `风量(m3/min):`,
|
|
|
+ font: 'normal 29px Arial',
|
|
|
+ color: '#009900',
|
|
|
+ strokeStyle: '#002200',
|
|
|
+ x: 2,
|
|
|
+ y: 115,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: `${selectData.m3 ? selectData.m3 : '-'}`,
|
|
|
+ font: 'normal 29px Arial',
|
|
|
+ color: '#009900',
|
|
|
+ strokeStyle: '#002200',
|
|
|
+ x: 200,
|
|
|
+ y: 115,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: `气源压力(MPa): `,
|
|
|
+ font: 'normal 29px Arial',
|
|
|
+ color: '#009900',
|
|
|
+ strokeStyle: '#002200',
|
|
|
+ x: 2,
|
|
|
+ y: 182,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: `${selectData.temperature ? selectData.temperature : '-'}`,
|
|
|
+ font: 'normal 29px Arial',
|
|
|
+ color: '#009900',
|
|
|
+ strokeStyle: '#002200',
|
|
|
+ x: 215,
|
|
|
+ y: 182,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: `Va(m/s):`,
|
|
|
+ font: 'normal 29px Arial',
|
|
|
+ color: '#009900',
|
|
|
+ strokeStyle: '#002200',
|
|
|
+ x: 2,
|
|
|
+ y: 245,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: `${selectData.va ? selectData.va : '-'}`,
|
|
|
+ font: 'normal 29px Arial',
|
|
|
+ color: '#009900',
|
|
|
+ strokeStyle: '#002200',
|
|
|
+ x: 130,
|
|
|
+ y: 246,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: `V1(m/s):`,
|
|
|
+ font: 'normal 28px Arial',
|
|
|
+ color: '#009900',
|
|
|
+ strokeStyle: '#002200',
|
|
|
+ x: 331,
|
|
|
+ y: 115,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: `${selectData.incipientWindSpeed1 ? selectData.incipientWindSpeed1 : '-'}`,
|
|
|
+ font: 'normal 28px Arial',
|
|
|
+ color: '#009900',
|
|
|
+ strokeStyle: '#002200',
|
|
|
+ x: 455,
|
|
|
+ y: 115,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: `V2(m/s):`,
|
|
|
+ font: 'normal 28px Arial',
|
|
|
+ color: '#009900',
|
|
|
+ strokeStyle: '#002200',
|
|
|
+ x: 330,
|
|
|
+ y: 182,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: `${selectData.incipientWindSpeed2 ? selectData.incipientWindSpeed2 : '-'}`,
|
|
|
+ font: 'normal 28px Arial',
|
|
|
+ color: '#009900',
|
|
|
+ strokeStyle: '#002200',
|
|
|
+ x: 452,
|
|
|
+ y: 182,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: `V3(m/s):`,
|
|
|
+ font: 'normal 28px Arial',
|
|
|
+ color: '#009900',
|
|
|
+ strokeStyle: '#002200',
|
|
|
+ x: 330,
|
|
|
+ y: 245,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: `${selectData.incipientWindSpeed3 ? selectData.incipientWindSpeed3 : '-'}`,
|
|
|
+ font: 'normal 28px Arial',
|
|
|
+ color: '#009900',
|
|
|
+ strokeStyle: '#002200',
|
|
|
+ x: 452,
|
|
|
+ y: 245,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: `煤炭科学技术研究院有限公司研制`,
|
|
|
+ font: 'normal 28px Arial',
|
|
|
+ color: '#009900',
|
|
|
+ strokeStyle: '#002200',
|
|
|
+ x: 60,
|
|
|
+ y: 302,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ getTextCanvas(560, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
|
|
|
+ const textMap = new THREE.CanvasTexture(canvas); // 关键一步
|
|
|
+ const textMaterial = new THREE.MeshBasicMaterial({
|
|
|
+ map: textMap, // 设置纹理贴图
|
|
|
+ transparent: true,
|
|
|
+ side: THREE.DoubleSide, // 这里是双面渲染的意思
|
|
|
+ });
|
|
|
+ textMaterial.blending = THREE.CustomBlending;
|
|
|
+ const monitorPlane = this.group?.getObjectByName('monitorText');
|
|
|
+ if (monitorPlane) {
|
|
|
+ monitorPlane.material = textMaterial;
|
|
|
+ } else {
|
|
|
+ const planeGeometry = new THREE.PlaneGeometry(560, 346); // 平面3维几何体PlaneGeometry
|
|
|
+ const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
|
|
|
+ planeMesh.name = 'monitorText';
|
|
|
+ planeMesh.scale.set(0.0022, 0.0022, 0.0022);
|
|
|
+ planeMesh.position.set(3.25, -0.002, -0.41);
|
|
|
+ this.group?.add(planeMesh);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 提取风门序列帧,初始化前后门动画 */
|
|
|
+ initAnimation() {}
|
|
|
+
|
|
|
+ /* 点击 */
|
|
|
+ mousedownModel(intersects: THREE.Intersection<THREE.Object3D<THREE.Event>>[]) {
|
|
|
+ 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;
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理杯子的纹理和杯子外层透明壳子
|
|
|
+ */
|
|
|
+ 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);
|
|
|
+ };
|
|
|
+
|
|
|
+ mountedThree() {
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ this.model.setModel([this.modelName]).then(async (gltf) => {
|
|
|
+ const nitrogenGroup = new THREE.Object3D();
|
|
|
+ const nitrogenModal = gltf[0].clone();
|
|
|
+ nitrogenModal.name = 'nitrogenModal0';
|
|
|
+ nitrogenModal;
|
|
|
+
|
|
|
+ const nitrogenModal1 = gltf[0].clone();
|
|
|
+ nitrogenModal1.name = 'nitrogenModal1';
|
|
|
+ nitrogenModal1.position.set(0, 0, 1.29);
|
|
|
+
|
|
|
+ const texture = await addEnvMap('royal_esplanade_1k', this.model);
|
|
|
+
|
|
|
+ const material = new THREE.MeshPhysicalMaterial({
|
|
|
+ side: THREE.DoubleSide,
|
|
|
+ // specularColor: new Color("#ffffff"),
|
|
|
+ // color: new Color(0xffa000),
|
|
|
+ color: 0xffffff,
|
|
|
+ //类似透明度
|
|
|
+ // transmission: 0.5,
|
|
|
+ opacity: 0,
|
|
|
+ metalness: 0,
|
|
|
+ roughness: 0.12,
|
|
|
+ ior: 1.8,
|
|
|
+ thickness: 0.39, //透过看物体的模糊程度
|
|
|
+ specularIntensity: 1.1,
|
|
|
+ // color: new THREE.Color(0x72531e),
|
|
|
+ transmission: 1,
|
|
|
+ // envMap: texture,
|
|
|
+ });
|
|
|
+
|
|
|
+ nitrogenModal.children[0].children[1].material = new THREE.MeshPhysicalMaterial({
|
|
|
+ side: THREE.DoubleSide,
|
|
|
+ transparent: true,
|
|
|
+ opacity: 0.1,
|
|
|
+ color: 0xffffff,
|
|
|
+ //类似透明度
|
|
|
+ // transmission: 0.5,
|
|
|
+ metalness: 0,
|
|
|
+ roughness: 0.2,
|
|
|
+ ior: 1.3,
|
|
|
+ thickness: 1.2, //透过看物体的模糊程度
|
|
|
+ specularIntensity: 1,
|
|
|
+ // color: new THREE.Color(0x72531e),
|
|
|
+ transmission: 0,
|
|
|
+ });
|
|
|
+
|
|
|
+ gui.add(material, 'metalness', 0, 1).onChange(function (value) {
|
|
|
+ material.metalness = Number(value);
|
|
|
+ });
|
|
|
+ gui.add(material, 'roughness', 0, 1).onChange(function (value) {
|
|
|
+ material.roughness = Number(value);
|
|
|
+ });
|
|
|
+ gui.add(material, 'thickness', 0, 2).onChange(function (value) {
|
|
|
+ material.thickness = Number(value);
|
|
|
+ });
|
|
|
+ gui.add(material, 'specularIntensity', 0, 2).onChange(function (value) {
|
|
|
+ material.specularIntensity = Number(value);
|
|
|
+ });
|
|
|
+ gui.add(material, 'transmission', 0, 1).onChange(function (value) {
|
|
|
+ material.transmission = Number(value);
|
|
|
+ });
|
|
|
+ gui.add(material, 'ior', 0, 3).onChange(function (value) {
|
|
|
+ material.ior = Number(value);
|
|
|
+ });
|
|
|
+
|
|
|
+ nitrogenModal.children[0].children[0].material = material;
|
|
|
+
|
|
|
+ nitrogenGroup.add(nitrogenModal);
|
|
|
+ nitrogenGroup.add(nitrogenModal1);
|
|
|
+
|
|
|
+ this.group = nitrogenGroup;
|
|
|
+ this.group.name = this.modelName;
|
|
|
+
|
|
|
+ // this.handleGlassAndWrap(
|
|
|
+ // this.group,
|
|
|
+ // withVolume,
|
|
|
+ // glass1,
|
|
|
+ // roughnessParams,
|
|
|
+ // 10,
|
|
|
+ // new THREE.Vector3(60, -2.4, -120),
|
|
|
+ // new THREE.Vector3(1.5, 1, -3)
|
|
|
+ // );
|
|
|
+ // this.handleGlassAndWrap(
|
|
|
+ // objects,
|
|
|
+ // withVolume,
|
|
|
+ // glass3,
|
|
|
+ // { ...roughnessParams, color: new THREE.Color(0x72531e), transmission: 0.7 },
|
|
|
+ // 5,
|
|
|
+ // new THREE.Vector3(-42, -2.5, -97)
|
|
|
+ // );
|
|
|
+
|
|
|
+ this.setModalPosition();
|
|
|
+ this.addLight();
|
|
|
+ resolve(null);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ destroy() {
|
|
|
+ if (this.group) {
|
|
|
+ this.model.clearGroup(this.group);
|
|
|
+ }
|
|
|
+ this.model = null;
|
|
|
+ this.group = null;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export default Nitrogen;
|