|
|
@@ -0,0 +1,248 @@
|
|
|
+import * as THREE from 'three';
|
|
|
+import { useAppStore } from '/@/store/modules/app';
|
|
|
+
|
|
|
+import * as dat from 'dat.gui';
|
|
|
+const gui = new dat.GUI();
|
|
|
+gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
|
|
|
+
|
|
|
+// 羊马河
|
|
|
+class FireDoorYmh {
|
|
|
+ modelName = 'fireDoorYmh';
|
|
|
+ model; //
|
|
|
+ group;
|
|
|
+ isLRAnimation = true; // 是否开启左右摇摆动画
|
|
|
+ direction = 1; // 摇摆方向
|
|
|
+ animationTimer: NodeJS.Timeout | null = null; // 摇摆开启定时器
|
|
|
+ player1;
|
|
|
+ player2;
|
|
|
+ deviceDetailCSS3D;
|
|
|
+ playerStartClickTime1 = new Date().getTime();
|
|
|
+ playerStartClickTime2 = new Date().getTime();
|
|
|
+
|
|
|
+ fmClock = new THREE.Clock();
|
|
|
+ mixers: THREE.AnimationMixer | undefined;
|
|
|
+ appStore = useAppStore();
|
|
|
+ damperOpenMesh;
|
|
|
+ damperClosedMesh;
|
|
|
+
|
|
|
+ clipActionArr: Record<string, THREE.AnimationAction | undefined> = {
|
|
|
+ /** 卷帘门动画 */
|
|
|
+ fengmen: undefined,
|
|
|
+ /** 盖板动画 */
|
|
|
+ gaiban: undefined,
|
|
|
+ };
|
|
|
+
|
|
|
+ constructor(model) {
|
|
|
+ this.model = model;
|
|
|
+ }
|
|
|
+
|
|
|
+ addLight() {
|
|
|
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5);
|
|
|
+ directionalLight.position.set(344, 690, 344);
|
|
|
+ this.group?.add(directionalLight);
|
|
|
+ directionalLight.target = this.group as THREE.Object3D;
|
|
|
+
|
|
|
+ const pointLight2 = new THREE.PointLight(0xffeeee, 1, 300);
|
|
|
+ pointLight2.position.set(-4, 10, 1.8);
|
|
|
+ pointLight2.shadow.bias = 0.05;
|
|
|
+ this.group?.add(pointLight2);
|
|
|
+
|
|
|
+ const pointLight3 = new THREE.PointLight(0xffeeee, 1, 200);
|
|
|
+ pointLight3.position.set(-0.5, -0.5, 0.75);
|
|
|
+ pointLight3.shadow.bias = 0.05;
|
|
|
+ this.group?.add(pointLight3);
|
|
|
+ }
|
|
|
+ resetCamera() {
|
|
|
+ this.model.camera.far = 274;
|
|
|
+ this.model.orbitControls?.update();
|
|
|
+ this.model.camera.updateProjectionMatrix();
|
|
|
+ }
|
|
|
+ // 设置模型位置
|
|
|
+ setModalPosition() {
|
|
|
+ this.group?.scale.set(24, 24, 24);
|
|
|
+ this.group?.position.set(-20, 20, 10);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 风门动画 */
|
|
|
+ render() {
|
|
|
+ if (!this.model) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (this.mixers && this.fmClock.running) {
|
|
|
+ this.mixers.update(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 点击风门 */
|
|
|
+ mousedownModel(intersects: THREE.Intersection[]) {
|
|
|
+ console.log('摄像头控制信息', intersects);
|
|
|
+ }
|
|
|
+
|
|
|
+ mouseUpModel() {}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 提取风门序列帧,初始化前后门动画
|
|
|
+ *
|
|
|
+ * 动画序列帧提取操作提示:使用threejs编辑器打开模型并选择模型后点击右下角播放后排查动画元素,找到分界点后手动标记或根据name标记
|
|
|
+ */
|
|
|
+ initAnimation() {
|
|
|
+ const group = this.group.children[0];
|
|
|
+ console.log('debug rr', group.animations[0].tracks);
|
|
|
+ /** 卷帘门的元素名称,pCude34-pCude73 */
|
|
|
+ if (group) {
|
|
|
+ const tracksA: THREE.KeyframeTrack[] = [];
|
|
|
+ const tracksB: THREE.KeyframeTrack[] = [];
|
|
|
+
|
|
|
+ group.animations[0].tracks.forEach((track, index) => {
|
|
|
+ if (index < 9) {
|
|
|
+ tracksA.push(track);
|
|
|
+ } else {
|
|
|
+ tracksB.push(track);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ this.mixers = new THREE.AnimationMixer(group);
|
|
|
+
|
|
|
+ const fengmen = new THREE.AnimationClip('fengmen', 10, tracksA);
|
|
|
+ const clipA = this.mixers.clipAction(fengmen, group);
|
|
|
+ clipA.clampWhenFinished = true;
|
|
|
+ clipA.loop = THREE.LoopOnce;
|
|
|
+ this.clipActionArr.fengmen = clipA;
|
|
|
+
|
|
|
+ const gaiban = new THREE.AnimationClip('gaiban', 10, tracksB);
|
|
|
+ const clipB = this.mixers.clipAction(gaiban, group);
|
|
|
+ clipB.clampWhenFinished = true;
|
|
|
+ clipB.loop = THREE.LoopOnce;
|
|
|
+ this.clipActionArr.gaiban = clipB;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ resetAnimate() {
|
|
|
+ if (this.clipActionArr.fengmen) {
|
|
|
+ this.clipActionArr.fengmen.reset();
|
|
|
+ this.clipActionArr.fengmen.time = 0.1;
|
|
|
+ this.clipActionArr.fengmen.stop();
|
|
|
+ this.fmClock.stop();
|
|
|
+ }
|
|
|
+ if (this.clipActionArr.gaiban) {
|
|
|
+ this.clipActionArr.gaiban.reset();
|
|
|
+ this.clipActionArr.gaiban.time = 0.1;
|
|
|
+ this.clipActionArr.gaiban.stop();
|
|
|
+ this.fmClock.stop();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 播放门开关动画的处理函数
|
|
|
+ * @param {number} handlerState - 处理状态,1表示开门,2表示关门
|
|
|
+ * @param {number} [timeScale=0.01] - 动画时间缩放因子,控制动画播放速度
|
|
|
+ */
|
|
|
+ play(handlerState, timeScale = 0.01) {
|
|
|
+ console.log('debug ', handlerState);
|
|
|
+ let handler = () => {};
|
|
|
+ switch (handlerState) {
|
|
|
+ case 1: // 打开门
|
|
|
+ handler = () => {
|
|
|
+ if (!this.clipActionArr.fengmen) return;
|
|
|
+ this.clipActionArr.fengmen.paused = true;
|
|
|
+ this.clipActionArr.fengmen.reset();
|
|
|
+ this.clipActionArr.fengmen.time = 0.1;
|
|
|
+ this.clipActionArr.fengmen.timeScale = timeScale;
|
|
|
+ // this.clipActionArr.fengmen.clampWhenFinished = true;
|
|
|
+ this.clipActionArr.fengmen.play();
|
|
|
+ this.fmClock.start();
|
|
|
+
|
|
|
+ // 显示打开前门文字
|
|
|
+ if (this.damperOpenMesh) this.damperOpenMesh.visible = true;
|
|
|
+ };
|
|
|
+ break;
|
|
|
+ case 2: // 关闭门
|
|
|
+ handler = () => {
|
|
|
+ if (!this.clipActionArr.fengmen) return;
|
|
|
+ this.clipActionArr.fengmen.paused = true;
|
|
|
+ this.clipActionArr.fengmen.reset(); //
|
|
|
+ this.clipActionArr.fengmen.time = 9;
|
|
|
+ this.clipActionArr.fengmen.timeScale = -timeScale;
|
|
|
+ // this.clipActionArr.fengmen.clampWhenFinished = true;
|
|
|
+ this.clipActionArr.fengmen.play();
|
|
|
+ this.fmClock.start();
|
|
|
+
|
|
|
+ if (this.damperOpenMesh) this.damperOpenMesh.visible = false;
|
|
|
+ };
|
|
|
+ break;
|
|
|
+ case 3: // 打开盖板
|
|
|
+ handler = () => {
|
|
|
+ if (!this.clipActionArr.gaiban) return;
|
|
|
+ this.clipActionArr.gaiban.paused = true;
|
|
|
+ this.clipActionArr.gaiban.reset();
|
|
|
+ this.clipActionArr.gaiban.time = 0.1;
|
|
|
+ this.clipActionArr.gaiban.timeScale = timeScale;
|
|
|
+ // this.clipActionArr.gaiban.clampWhenFinished = true;
|
|
|
+ this.clipActionArr.gaiban.play();
|
|
|
+ this.fmClock.start();
|
|
|
+
|
|
|
+ if (this.damperOpenMesh) this.damperOpenMesh.visible = false;
|
|
|
+ };
|
|
|
+ break;
|
|
|
+ case 4: // 关闭盖板
|
|
|
+ handler = () => {
|
|
|
+ if (!this.clipActionArr.gaiban) return;
|
|
|
+ this.clipActionArr.gaiban.paused = true;
|
|
|
+ this.clipActionArr.gaiban.reset(); //
|
|
|
+ this.clipActionArr.gaiban.time = 9;
|
|
|
+ this.clipActionArr.gaiban.timeScale = -timeScale;
|
|
|
+ // this.clipActionArr.gaiban.clampWhenFinished = true;
|
|
|
+ this.clipActionArr.gaiban.play();
|
|
|
+ this.fmClock.start();
|
|
|
+
|
|
|
+ if (this.damperOpenMesh) this.damperOpenMesh.visible = false;
|
|
|
+ };
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ }
|
|
|
+ handler();
|
|
|
+ }
|
|
|
+
|
|
|
+ mountedThree() {
|
|
|
+ this.group = new THREE.Object3D();
|
|
|
+ this.group.name = this.modelName;
|
|
|
+
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ if (!this.model) {
|
|
|
+ resolve(null);
|
|
|
+ }
|
|
|
+ this.model.setGLTFModel(['fireDoorYmh'], this.group).then(() => {
|
|
|
+ this.setModalPosition();
|
|
|
+ // 初始化左右摇摆动画;
|
|
|
+ this.initAnimation();
|
|
|
+ // this.addLight();
|
|
|
+ // this.model.animate();
|
|
|
+ // resolve(this.model);
|
|
|
+
|
|
|
+ // this.damperOpenMesh = this.group.getObjectByName('Damper_Open_2');
|
|
|
+ // if (this.damperOpenMesh) this.damperOpenMesh.visible = false;
|
|
|
+ // this.damperClosedMesh = this.group.getObjectByName('Damper_Closed_2');
|
|
|
+ // if (this.damperClosedMesh) this.damperClosedMesh.visible = true;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ destroy() {
|
|
|
+ if (!this.model) return;
|
|
|
+ if (this.mixers && this.clipActionArr.fengmen && this.clipActionArr.gaiban) {
|
|
|
+ this.mixers.uncacheClip(this.clipActionArr.fengmen.getClip());
|
|
|
+ this.mixers.uncacheAction(this.clipActionArr.fengmen.getClip(), this.group);
|
|
|
+ this.mixers.uncacheClip(this.clipActionArr.gaiban.getClip());
|
|
|
+ this.mixers.uncacheAction(this.clipActionArr.gaiban.getClip(), this.group);
|
|
|
+ this.mixers.uncacheRoot(this.group);
|
|
|
+
|
|
|
+ if (this.model.animations[0]) this.model.animations[0].tracks = [];
|
|
|
+ }
|
|
|
+ this.model.clearGroup(this.group);
|
|
|
+ this.clipActionArr.fengmen = undefined;
|
|
|
+ this.clipActionArr.gaiban = undefined;
|
|
|
+
|
|
|
+ this.mixers = undefined;
|
|
|
+
|
|
|
+ // document.getElementById('damper3D').parentElement.remove(document.getElementById('damper3D'))
|
|
|
+ }
|
|
|
+}
|
|
|
+export default FireDoorYmh;
|