<template>
    <div>
        <canvas id="three"></canvas>
        <div class="button" @click="toHomeView">
            主视角
        </div>
    </div>
   
</template>
<script setup>
import * as THREE from "three";
import { ref, onMounted } from "vue";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
// 引入轨道控制器:支持鼠标左中右键操作和键盘方向键操作
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
import {
    CSS2DObject,
    CSS2DRenderer,
} from "three/examples/jsm/renderers/CSS2DRenderer";
// import renderModel from "../renderModel";
import homeIcon from '@/assets/image/bg7.jpg'
import TWEEN from "@tweenjs/tween.js";
import bus from '@/utils/bus.js'

let scene = ref(null);
let renderer = ref(null);
let camera = ref(null);
// 控制器
let orbit = ref(null);
let group = ref(null);
let mouse = new THREE.Vector2();
let raycaster = new THREE.Raycaster();
let labelRenderer = new CSS2DRenderer(); //新建CSS2DRenderer
let positionObj = ref(null);
// 选中的模型
let selectedObjects = ref([]);

const props = defineProps({
    background: { // 背景颜色
        default: '#fff',
        type: String
    },
    sceneUrl: { // 模型路径
        default: '/jz/glb/scene.gltf',
        type: String
    },
    light: {
        default: '0xffffff',
        type: String
    }
})
const data = reactive({
    reductionMaterial: null
});
const { reductionMaterial } = toRefs(data);

watch(() => props.sceneUrl, val => {
    init();
    loadSence();
});
onMounted(() => {
    bus.on('foo', e => {
         
    })
    init();
    loadSence();
    // 启动动画
    renderScene();
    document.addEventListener("click", onMouseDown);
});
const init = () => {
    scene = new THREE.Scene("#00ffff");
    const texture = new THREE.TextureLoader().load(homeIcon);
    texture.mapping = THREE.EquirectangularReflectionMapping;
    scene.background = texture
    scene.environment = texture

    const canvas = document.querySelector("#three");
    var cubeLoader = new THREE.CubeTextureLoader();
    // 创建一个渲染器并设置大小，WebGLRenderer将会使用电脑显卡来渲染场景
    renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true, preserveDrawingBuffer: true });
    //曝光
    renderer.toneMappingExposure = 2;
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;

    camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.25, 2000)
    // 将摄像机对准场景的中心
    camera.position.set(0, 104.545, -21.637);
    // camera.lookAt(scene.position);
   
    // 创建控件对象
    orbit = new OrbitControls(camera, renderer.domElement);
    orbit.autoRotate = true;
    setTimeout(function () {
        orbit.autoRotate = false;
    }, 7000);
    renderer.setClearColor(new THREE.Color("#0e0934"));
    renderer.setSize(window.innerWidth, window.innerHeight);
    // 环境光 光源颜色从0x444444更改为0x888888,可以看到threejs场景中的网格模型表面变的更亮。
    // intensity 强度属性0.5
    var alight = new THREE.AmbientLight(props.light, 0.5);
    alight.name = "aLight";
    scene.add(alight);
};

const loadSence = () => {
    const gltfLoader = new GLTFLoader();
    gltfLoader.load(props.sceneUrl, (gltf) => {
        var model = gltf.scene;
        scene.add(model);
    });
};

const renderScene = () => {
    orbit.update(); // 拖动
    // 使用requestAnimationFrame函数进行渲染
    requestAnimationFrame(renderScene);
    renderer.render(scene, camera);
    // 写在requestAnimationFrame之后,否则会报错
    labelRenderer.render(scene, camera);
};
// 相机移动动画
const initTween = (targetX, targetY, targetZ) => {
    let initPosition = {
        x: camera.position.x,
        y: camera.position.y,
        z: camera.position.z,
    };
    let tween = new TWEEN.Tween(initPosition)
    .to({ x: targetX, y: targetY, z: targetZ }, 2000)
    .easing(TWEEN.Easing.Sinusoidal.InOut);
    let onUpdate = (pos) => {
    let x = pos.x;
    let y = pos.y;
    let z = pos.z;
    if (pos.z < 0) {
        camera.position.set(x, y, z - 12);
    } else {
        camera.position.set(x, y, z + 12);
    }
    };
    tween.onUpdate(onUpdate);
    tween.start();
    if (positionObj.z < 0) {
        orbit.target.set(
            positionObj.x,
            positionObj.y - 0.4,
            -12
        );
    } else {
        orbit.target.set(
            positionObj.x,
            positionObj.y - 0.4,
            12
        );
    }
}

// 储存被选中的模型和材质
let selectedObject = null;
let selectedMaterial = null;

const onMouseDown = (event) => {
    var raycaster = new THREE.Raycaster()
    // 恢复之前被选中模型的材质
    if (selectedObject && selectedMaterial) {
        selectedObject.material = selectedMaterial;
        selectedObject = null;
        selectedMaterial = null;
    }
    // 计算鼠标点击位置的归一化设备坐标
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

    // 更新射线的起点和方向
    raycaster.setFromCamera(mouse, camera);
    // 计算射线和场景中所有可点击物体的相交情况
    const intersects = raycaster.intersectObjects(scene.children, true);
    // 如果找到了模型，将其材质修改为绿色
    if (intersects.length > 0) {
        const clickedObject = intersects[0].object;
        // 储存被选中的模型和材质
        selectedObject = clickedObject;
        selectedMaterial = clickedObject.material;
        // 修改材质为绿色
        selectedObject.material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
    }
    // 拉近场景
    if (!intersects[0]) {
        return;
    } else {
    
        if (intersects[0].object.name.indexOf('box') > -1) {
            selectedObjects = [];
            selectedObjects.push(intersects[0].object);
            positionObj = {
            x: intersects[0].object.position.x,
            y: intersects[0].object.position.y,
            z: intersects[0].object.position.z,
            };

            initTween(
                positionObj.x,
                positionObj.y,
                positionObj.z
            );
        }
    }
}
// 返回主页
const toHomeView = () => { 
    let initPosition = {
        x: camera.position.x,
        y: camera.position.y,
        z: camera.position.z,
    };
    let tween = new TWEEN.Tween(initPosition)
        .to({ x: 0, y: -(5 * 24) / 12, z: (6 * 100) / 5 }, 2000)
        .easing(TWEEN.Easing.Sinusoidal.InOut);
    let onUpdate = (pos) => {
        let x = pos.x;
        let y = pos.y;
        let z = pos.z;
        camera.position.set(x, y, z);
    };
    tween.onUpdate(onUpdate);
    tween.start();
    orbit.target.set(0, 0, 0);
}
</script>
<style lang='scss' scoped>
#three {
    height: 100%;
    width: 100%;
}
.button {
    width: 80px;
    height: 80px;
    line-height: 80px;
    border-radius: 50%;
    border: 1px solid rgb(7, 207, 221);
    position: absolute;
    z-index: 1000000;
    bottom: 15px;
    left: 10px;
    color: #fff;
    text-align: center; 
    background: rgb(7, 207, 221);
    cursor: pointer;
}
</style>