<template>
    <div>
        <div id="containerThreeSensorModel"></div>
    </div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { ConvexGeometry } from "three/examples/jsm/geometries/ConvexGeometry.js";

export default {
    name: "threeSensorModel", // 传感器模型中的threeJS
    components: {},

    data() {
        return {
            publicPath: process.env.BASE_URL,
            scene: null,
            camera: null,
            renderer: null,
            light: null,
            transformControls: null,
            geometryName: null,
            controls: null,
            mesh: null,
            cube: null,
            cacheList: [],
            container: null,
            car: null,
            cubeTexture: null,
            raf: null,
            canDrag: true, // 是否可移动
            dragControls: null,
            scale: 1.5, // 物体加载换算倍数
        };
    },

    props: {
        coordinate: {
            type: Object,
            default: { f: 0, n: 0, h: 0, v: 0 },
        },
        coordinateA: {
            type: Object,
            default: { f: 0, n: 0, hl: 0, hr: 0, vl: 0, vb: 0 },
        },
        type: {
            type: Number,
            default: 1,
        },
    },

    methods: {
        // 场景
        initScene() {
            this.scene = new THREE.Scene();
            let axes = new THREE.AxesHelper(1500);
            this.scene.add(axes);
            const gridHelper = new THREE.GridHelper(1000, 100);
            gridHelper.material.opacity = 0.25;
            gridHelper.material.transparent = true;
            this.scene.add(gridHelper);
        },
        // 相机
        initCamera() {
            /* this.camera = new THREE.OrthographicCamera(
                this.container.clientWidth / -2,
                this.container.clientWidth / 2,
                this.container.clientHeight / 2,
                this.container.clientHeight / -2,
                1,
                // 0.1,
                1000
            ); */

            this.camera = new THREE.PerspectiveCamera(
                75,
                this.container.clientWidth / this.container.clientHeight,
                0.1,
                1000
            );
            // this.camera.layers.set(1);

            // this.camera = new THREE.PerspectiveCamera(45, 1.5, 1, 1000);
            // this.camera.position.set(600, 600, 600);
            this.camera.position.set(200, 200, 200);
            // this.camera.lookAt(this.scene.position);
            this.scene.add(this.camera);
        },
        // 渲染器
        initRenderer() {
            this.renderer = new THREE.WebGLRenderer({
                antialias: true,
                alpha: true,
            });
            this.renderer.setSize(
                this.container.clientWidth,
                this.container.clientHeight
            );
            this.renderer.setClearColor("#272727");
            this.container.appendChild(this.renderer.domElement);
        },
        // 初始化灯光
        initLight() {
            var hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
            hemiLight.position.set(0, 20, 0);
            this.scene.add(hemiLight);

            // 环境光会均匀的照亮场景中的所有物体
            const light = new THREE.AmbientLight(0x5c5c5c, 0.4); // soft white light
            this.scene.add(light);

            // 点光源
            // const light1 = new THREE.PointLight(0xffffff, 2, 100);
            // light1.position.set(0, 0, -100);
            // this.scene.add(light1);

            // 平行光是沿着特定方向发射的光
            const dirLight = new THREE.DirectionalLight(0xffffff, 0.5);
            // const dirLight = new THREE.DirectionalLight(0xffffff);
            // dirLight.position.set(0, 200, 100);
            // dirLight.castShadow = true;
            // dirLight.shadow.camera.top = 180;
            // dirLight.shadow.camera.bottom = -100;
            // dirLight.shadow.camera.left = -120;
            // dirLight.shadow.camera.right = 120;

            // dirLight.shadow.camera.near = 0.01;
            // dirLight.shadow.camera.far = 60;
            // dirLight.shadow.camera.top = 22;
            // dirLight.shadow.camera.bottom = -22;
            // dirLight.shadow.camera.left = -35;
            // dirLight.shadow.camera.right = 35;
            // // //设置阴影分辨率
            // dirLight.shadow.mapSize.width = 2048; // default
            // dirLight.shadow.mapSize.height = 2048; // default
            // //阴影限制
            // dirLight.shadow.radius = 1;
            this.scene.add(dirLight);

            // const spotLight = new THREE.SpotLight(0xffffff);
            // spotLight.position.set(100, 1000, 100);

            // spotLight.castShadow = true;

            // spotLight.shadow.mapSize.width = 1024;
            // spotLight.shadow.mapSize.height = 1024;

            // spotLight.shadow.camera.near = 500;
            // spotLight.shadow.camera.far = 4000;
            // spotLight.shadow.camera.fov = 30;

            // this.scene.add(spotLight);
        },
        // 初始化模型
        initContent() {
            const obj = this.scene.getObjectByName("cube");
            if (obj) {
                this.scene.remove(obj);
                this.clearCache(obj);
            }

            if (this.type != 2) {
                let r = this.coordinate.f;
                let r1 = this.coordinate.n;

                if (r <= 0 || r1 < 0 || r <= r1) {
                    return;
                }

                this.initSenA(r * this.scale, r1 * this.scale);
            } else {
                let r = this.coordinateA.f;
                let r1 = this.coordinateA.n;

                if (r <= 0 || r1 < 0 || r <= r1) {
                    return;
                }

                this.initSenB(r * this.scale, r1 * this.scale);
            }
        },
        // 处理轴对称物体
        initSenA(r, r1) {
            let x = 0,
                y = 0,
                z = r;

            let a = this.coordinate.h,
                b = this.coordinate.v;

            if (a >= 90) a = 89.99;
            if (b >= 90) b = 89.99;
            // console.log(Math.tan(THREE.MathUtils.degToRad(0)));

            x = Math.tan(THREE.MathUtils.degToRad(a)) * r;
            y = Math.tan(THREE.MathUtils.degToRad(b)) * r;

            let pointsArr = [];

            if (r1 === 0) {
                pointsArr = [
                    [0, 0, 0],
                    [x, y, z],
                    [x, -y, z],
                    [-x, -y, z],
                    [-x, y, z],
                ];
            } else {
                let x1 = 0,
                    y1 = 0,
                    z1 = r1;

                x1 = Math.tan(THREE.MathUtils.degToRad(a)) * r1;
                y1 = Math.tan(THREE.MathUtils.degToRad(b)) * r1;

                pointsArr = [
                    [x1, y1, z1],
                    [x1, -y1, z1],
                    [-x1, -y1, z1],
                    [-x1, y1, z1],
                    [x, y, z],
                    [x, -y, z],
                    [-x, -y, z],
                    [-x, y, z],
                ];
            }

            this.initMesh(pointsArr);
        },
        // 处理非轴对称物体
        initSenB(r, r1) {
            let x1 = 0,
                x2 = 0,
                y1 = 0,
                y2 = 0,
                z1 = r;

            let a = this.coordinateA.hl,
                b = this.coordinateA.vt,
                c = this.coordinateA.hr,
                d = this.coordinateA.vb;

            if (a >= 90) a = 89.99;
            if (b >= 90) b = 89.99;
            if (c >= 90) c = 89.99;
            if (d >= 90) d = 89.99;

            x1 = Math.tan(THREE.MathUtils.degToRad(a)) * r;
            y1 = Math.tan(THREE.MathUtils.degToRad(b)) * r;
            x2 = Math.tan(THREE.MathUtils.degToRad(c)) * r;
            y2 = Math.tan(THREE.MathUtils.degToRad(d)) * r;

            let pointsArr = [];

            if (r1 === 0) {
                pointsArr = [
                    [0, 0, 0],
                    [x1, y1, z1],
                    [x1, -y2, z1],
                    [-x2, -y2, z1],
                    [-x2, y1, z1],
                ];
            } else {
                let m1 = 0,
                    m2 = 0,
                    n1 = 0,
                    n2 = 0,
                    z2 = r1;

                m1 = Math.tan(THREE.MathUtils.degToRad(a)) * r1;
                n1 = Math.tan(THREE.MathUtils.degToRad(b)) * r1;
                m2 = Math.tan(THREE.MathUtils.degToRad(c)) * r1;
                n2 = Math.tan(THREE.MathUtils.degToRad(d)) * r1;

                pointsArr = [
                    [m1, n1, z2],
                    [m1, -n2, z2],
                    [-m2, -n2, z2],
                    [-m2, n1, z2],
                    [x1, y1, z1],
                    [x1, -y2, z1],
                    [-x2, -y2, z1],
                    [-x2, y1, z1],
                ];
            }

            this.initMesh(pointsArr);
        },
        initMesh(pointsArr) {
            let points = pointsArr.map(
                (d) => new THREE.Vector3(d[0], d[1], d[2])
            );

            let color = null;
            if (this.type === 1) {
                color = 0x0000ff;
            } else if (this.type === 2) {
                color = 0x008000;
            } else if (this.type === 3) {
                color = 0xff4500;
            } else {
                color = 0x0000ff;
            }

            let material = new THREE.MeshPhongMaterial({
                emissive: color,
                // shininess: 60,
                // specular: this.color,
                color: 0x4c4c4c,
                transparent: true,
                opacity: 0.3,
                lightMapIntensity: 0.1,
            });

            let tixing = new ConvexGeometry(points);
            //通过ConvexGeometry凸包绘制一个梯台，当然也可以使用ExtrudeGeometry挤压几何体，
            let tixingMesh = new THREE.Mesh(tixing, material);
            tixingMesh.name = "cube";
            this.scene.add(tixingMesh);
        },
        // 初始化
        init() {
            this.initScene();
            this.initCamera();
            this.initRenderer();
            this.initLight();
            // this.initContent();

            this.controls = new OrbitControls(
                this.camera,
                this.renderer.domElement
            ); //创建控件对象
            this.controls.update();
        },
        animate() {
            this.raf = requestAnimationFrame(this.animate);
            this.renderer.render(this.scene, this.camera);
            if (this.transformControls) {
                this.transformControls.update();
            }

            this.controls.update();
        },
        onWindowResize() {
            this.camera.aspect =
                this.container.clientWidth / this.container.clientHeight;
            this.camera.updateProjectionMatrix();
            this.renderer.setSize(
                this.container.clientWidth,
                this.container.clientHeight
            );
        },
        go() {
            this.container = document.getElementById(
                "containerThreeSensorModel"
            );
            this.init();
            this.animate();

            window.addEventListener("resize", this.onWindowResize);
        },
        removeScene() {
            this.clearScene();
        },
        clearCache(item) {
            if (item.geometry && item.geometry.dispose) item.geometry.dispose();
            if (item.material && item.material.dispose) item.material.dispose();
        },
        clearScene() {
            this.removeObj(this.scene);
        },
        removeObj(obj) {
            let arr = obj.children.filter((x) => x);
            arr.forEach((item) => {
                if (item.children.length) {
                    this.removeObj(item);
                } else {
                    this.clearCache(item);
                    item.clear();
                }
            }),
                obj.clear();
            arr = null;
        },
    },

    mounted() {
        this.go();
    },
    destroyed() {
        window.removeEventListener("resize", this.onWindowResize);
        cancelAnimationFrame(this.raf);

        if (this.renderer) {
            this.renderer.renderLists.dispose();
            this.renderer.dispose();
            this.renderer.forceContextLoss();
            this.renderer.domElement = null;
            this.renderer.content = null;
            this.renderer = null;
        }

        if (this.dragControls) {
            this.dragControls.deactivate();
            this.dragControls.dispose();
            this.dragControls = null;
        }

        if (this.controls) {
            this.controls.dispose();
            this.controls = null;
        }

        if (this.transformControls) {
            this.transformControls.detach();
            this.transformControls.dispose();
            this.transformControls = null;
        }

        if (this.cacheList.length > 0) {
            this.scene.remove(...this.cacheList);
            this.cacheList = [];
        }

        this.clearScene();

        this.scene = null;
        this.camera = null;
        this.light = null;
        this.geometryName = null;
        this.mesh = null;
        this.cube = null;
        this.container = null;
        this.car = null;
        this.cubeTexture = null;
        this.raf = null;

        THREE.Cache.clear();
    },
};
</script>

<style lang="less" scoped>
#containerThreeSensorModel {
    width: 100%;
    height: calc(100vh - 180px);
}
</style>
