<template>
    <div class="three-model" @click="clickEvent">
        <loading ref="pageLoading"></loading>
    </div>
</template>

<script>
import loading from '@com/coms/loading/loading.vue';
import * as THREE from "three";
import { GLTFLoader } from "@node/three/examples/jsm/loaders/GLTFLoader.js";
import { OrbitControls } from "@node/three/examples/jsm/controls/OrbitControls.js";
let camera, scene, renderer, controls;
let mixers = [];
let clock = new THREE.Clock();
let fanAnimates = [];
export default {
    // 名称
    name: "ThreeModel",
    // 使用组件
    components: {
        loading
    },
    // 传入参数
    props: {},
    // 自定义事件
    emits: {
        when: null,
    },
    // 数据
    data() {
        return {
            // 场景
            initScene: function () {
                scene = new THREE.Scene();
                // scene.background = new THREE.Color(0xa0a0a0);
            },
            // 相机
            initCamera: function () {
                camera = new THREE.PerspectiveCamera(45, this.$el.scrollWidth / this.$el.scrollHeight, 0.1, 10000);
                camera.position.set(50, 60, 50);
            },
            // 坐标轴
            initAxesHelper: function () {
                const axesHelper = new THREE.AxesHelper(150);
                scene.add(axesHelper);
                axesHelper.position.set(0, 0, 0);
            },
            // 渲染器
            initRender: function () {
                renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
                // renderer.setClearAlpha(0);
                renderer.setSize(this.$el.scrollWidth, this.$el.scrollHeight);
                this.$el.append(renderer.domElement);
            },
            // 灯光
            initLight: function () {
                // let light = new THREE.PointLight(0xffffff, 2);
                let light = new THREE.AmbientLight(0xffffff, 4);
                // light.position.set(50, 50, 50);
                scene.add(light);
            },
            // 控制器
            initControls: function () {
                controls = new OrbitControls(camera, renderer.domElement);
            },
            // 初始化一个风机动画
            initFanAnimate: function (fan1, fan2, fan3) {
                let fanAnimateObj = {
                    speed: 0.05,
                    fan1: fan1,
                    fan2: fan2,
                    fan3: fan3,
                };
                let fanAnimateFunction = function () {
                    fanAnimateObj.fan1.rotateZ(fanAnimateObj.speed);
                    fanAnimateObj.fan2.rotateZ(fanAnimateObj.speed);
                    fanAnimateObj.fan3.rotateZ(fanAnimateObj.speed);
                    fanAnimateObj.animateId = window.requestAnimationFrame(fanAnimateFunction);
                }
                fanAnimateObj.stop = function () {
                    window.cancelAnimationFrame(fanAnimateObj.animateId);
                };
                fanAnimateObj.start = function () {
                    fanAnimateFunction();
                };
                fanAnimateFunction();
                fanAnimates.push(fanAnimateObj);
                return fanAnimateObj;
            },
            // 清空风机动画
            clearFanAnimate: function () {
                while (fanAnimates.length > 0) {
                    let fanAnimateObj = fanAnimates.shift();
                    fanAnimateObj.stop();
                }
            },
            // 内容
            initContent: function () {
                // 加载3D地面
                let loaderGround = new GLTFLoader();/*实例化加载器*/
                loaderGround.load("static/3d/group/ng.gltf", (gltf) => {
                    gltf.scene.position.set(5, 10, 0);
                    scene.add(gltf.scene);
                    // 找到一个大风扇的 Object3D
                    let fanBig1_1 = gltf.scene.children[0].getObjectByName("Box707");
                    let fanBig1_2 = gltf.scene.children[0].getObjectByName("Box708");
                    let fanBig1_3 = gltf.scene.children[0].getObjectByName("Box709");
                    let fanBig2_1 = gltf.scene.children[0].getObjectByName("Box719");
                    let fanBig2_2 = gltf.scene.children[0].getObjectByName("Box720");
                    let fanBig2_3 = gltf.scene.children[0].getObjectByName("Box721");
                    let fanBig3_1 = gltf.scene.children[0].getObjectByName("Box699");
                    let fanBig3_2 = gltf.scene.children[0].getObjectByName("Box701");
                    let fanBig3_3 = gltf.scene.children[0].getObjectByName("Box702");
                    this.initFanAnimate(fanBig1_1, fanBig1_2, fanBig1_3);
                    this.initFanAnimate(fanBig2_1, fanBig2_2, fanBig2_3);
                    this.initFanAnimate(fanBig3_1, fanBig3_2, fanBig3_3);
                    let mixer = new THREE.AnimationMixer(gltf.scene.children[0]); 
                    mixer.clipAction(gltf.animations[0]).setDuration(3).play();
                    mixers.push(mixer);
                    console.log(gltf)
                }, (xhr) => {
                    if (xhr.loaded == xhr.total) {
                        this.$emit("when");
                        setTimeout(() => {
                            this.$refs.pageLoading.hide();
                        }, 3000);
                    }
                }, function (error) {
                    console.error('load error!'+error.getWebGLErrorMessage());
                })
            },
            // 创建一个圆柱
            initCylinderGeometry: function () {
                let geometry = new THREE.CylinderGeometry(4, 4, 4, 64);
                let materials = [
                //圆柱侧面材质，使用纹理贴图
                new THREE.MeshBasicMaterial({
                    color: 0xffff00,
                    side: THREE.DoubleSide,
                    transparent: true
                }),
                //圆柱顶材质
                new THREE.MeshBasicMaterial({
                    transparent: true,
                    opacity: 0,
                    side: THREE.DoubleSide
                }),
                //圆柱底材质
                new THREE.MeshBasicMaterial({
                    transparent: true,
                    opacity: 0,
                    side: THREE.DoubleSide
                })
                ];
                let cylinder = new THREE.Mesh(geometry, materials);
                scene.add(cylinder);
            },
            // 点击事件
            clickEvent: function (event) {
                event.preventDefault();
                let vector = new THREE.Vector3(
                    (event.clientX / window.innerWidth) * 2 - 1,
                    -(event.clientY / window.innerHeight) * 2 + 1,
                    0.5
                );
                vector = vector.unproject(camera);
                let raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
                let intersects = raycaster.intersectObjects(scene.children,true);
                console.log(intersects)
                // this.initCylinderGeometry();
            },
            // 初始化
            initThree: function () {
                this.initScene();
                // this.initAxesHelper();
                this.initCamera();
                this.initRender();
                this.initLight();
                this.initControls();
                this.initContent();
                renderer.setAnimationLoop(this.animate);
            },
            // 动画
            animate: function () {
                var delta = clock.getDelta();
                for ( var i = 0; i < mixers.length; i ++ ) { // 重复播放动画
                    mixers[ i ].update( delta );
                }
                renderer.render(scene, camera);
            },
        };
    },
    // 函数
    methods: {},
    // 生命周期钩子
    beforeCreate() {
        // 创建前
    },
    created() {
        // 创建后
    },
    beforeMount() {
        // 渲染前
    },
    mounted() {
        // 渲染后
        this.initThree();
    },
    beforeUpdate() {
        // 数据更新前
    },
    updated() {
        // 数据更新后
    },
    beforeUnmount() {
        // 销毁前
        renderer.setAnimationLoop(null);
        camera = null;
        scene = null;
        renderer = null;
    },
};
</script>

<style lang="less" scoped>
.three-model {
}
</style>
