zhangliang2 2 жил өмнө
parent
commit
03858c4464

+ 627 - 0
src/views/workManagement/components/threeProjectInfo.vue

@@ -0,0 +1,627 @@
+<template>
+    <div>
+        <div id="containerThreeProjectInfo"></div>
+    </div>
+</template>
+
+<script>
+import * as THREE from "three";
+import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
+import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader.js";
+import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader.js";
+import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
+import {
+    showFullScreenLoading,
+    tryHideFullScreenLoading,
+} from "../../../axios/filter";
+
+export default {
+    name: "threeProjectInfo", // 项目详情中的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,
+            sensor: null, // 当前操作的传感器模型
+            ogt: null,
+            scale: 1.5, // 物体加载换算倍数
+            rate: 20, // 坐标换算倍数
+        };
+    },
+
+    props: {
+        carModel: {
+            type: String,
+            default: "",
+        },
+        // configList: {
+        //     type: Object,
+        //     default: {
+        //         camera: [],
+        //         ogt: [],
+        //         lidar: [],
+        //         gps: [],
+        //     },
+        // },
+    },
+
+    watch: {
+        carModel(newVal, oldVal) {
+            if (newVal && newVal != oldVal) {
+                this.initCar(newVal);
+            }
+        },
+        // configList(newVal, oldVal) {
+        // newVal, oldVal都没有值
+        //     if (newVal && newVal != oldVal) {
+        //         if (
+        //             newVal.camera.length > 0 ||
+        //             newVal.ogt.length > 0 ||
+        //             newVal.lidar.length > 0 ||
+        //             newVal.gps.length > 0
+        //         ) {
+        //             this.showAll();
+        //         }
+        //     }
+        // },
+    },
+
+    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.PerspectiveCamera(
+                75,
+                this.container.clientWidth / this.container.clientHeight,
+                0.1,
+                1000
+            );
+            this.camera.position.set(200, 200, 200);
+            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);
+            // this.scene.add(dirLight);
+        },
+        // 初始化模型
+        initContent(r, position, rotation, type) {
+            var cubeGeometry = new THREE.ConeGeometry(
+                r || 45 * this.scale,
+                150 * this.scale,
+                4,
+                1,
+                false
+            );
+            cubeGeometry.translate(0, -150, 0);
+
+            let obj = {
+                color: 0x4c4c4c,
+                transparent: true,
+                opacity: 0.3,
+                lightMapIntensity: 0.1,
+            };
+
+            if (type === "camera") {
+                obj.emissive = 0x0000ff;
+            } else if (type === "ogt") {
+                obj.emissive = 0x008000;
+            } else if (type === "lidar") {
+                obj.emissive = 0xff4500;
+            } else if (type === "gps") {
+                obj.emissive = 0x8a2be2;
+            }
+
+            var cubeMaterial = new THREE.MeshLambertMaterial(obj);
+            this.cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
+            this.cube.name = this.geometryName || "cube";
+
+            if (position) {
+                this.cube.position.x = position.x;
+                this.cube.position.y = position.y;
+                this.cube.position.z = position.z;
+            }
+
+            if (rotation) {
+                this.cube.rotateX(rotation.x);
+                this.cube.rotateY(rotation.y);
+                this.cube.rotateZ(rotation.z);
+            }
+
+            this.scene.add(this.cube);
+
+            if (this.transformControls) {
+                this.transformControls.attach(this.cube);
+            }
+        },
+        initCar0(model) {
+            if (this.car) {
+                console.log(this.car);
+                this.scene.remove(this.car);
+                this.removeObj(this.car);
+                this.car = null;
+            }
+
+            // const loading = this.$loading({
+            //     lock: true,
+            //     text: "模型加载中,请稍等...",
+            //     // spinner: "el-icon-loading",
+            //     background: "rgba(0, 0, 0, 0.2)",
+            // });
+
+            showFullScreenLoading();
+
+            var that = this;
+            var loader = new GLTFLoader(); //创建一个FBX加载器
+
+            // loader.load(`${this.publicPath}untitled.glb`, function (obj) {
+            loader.load(
+                model,
+                function (obj) {
+                    // loading.close();
+                    tryHideFullScreenLoading();
+
+                    obj.scene.rotation.set(
+                        (-90 * Math.PI) / 180,
+                        0,
+                        (-180 * Math.PI) / 180
+                    );
+
+                    let scale = 30 * that.scale;
+                    obj.scene.scale.set(scale, scale, scale);
+
+                    that.scene.add(obj.scene);
+                    that.car = obj.scene;
+                },
+                (xhr) => {
+                    // console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
+                },
+                (error) => {
+                    // loading.close();
+                    tryHideFullScreenLoading();
+                    console.error(error);
+                }
+            );
+        },
+        // 初始化车模型
+        initCar(model) {
+            console.log(model);
+            if (!model) return;
+            if (!model.includes(".glb")) return;
+
+            this.initCar0(model);
+        },
+        // 初始化
+        init() {
+            this.initScene();
+            this.initCamera();
+            this.initRenderer();
+            this.initLight();
+
+            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(
+                "containerThreeProjectInfo"
+            );
+            this.init();
+            this.animate();
+
+            window.addEventListener("resize", this.onWindowResize);
+        },
+        // 每编辑一个传感器则重新生成对应的物体
+        reset(type) {
+            this.canDrag = true;
+
+            if (this.cacheList.length > 0) {
+                this.scene.remove(...this.cacheList);
+                this.cacheList.forEach((i) => {
+                    this.clearCache(i);
+                });
+                this.cacheList = [];
+            }
+
+            this.sensor = null;
+
+            const obj1 = this.scene.getObjectByName("cube");
+            if (obj1) {
+                this.scene.remove(obj1);
+            }
+
+            this.xAngle = 0;
+            this.yAngle = 0;
+            this.zAngle = 0;
+
+            let x = +this.$parent.formA.sensorX || 0;
+            let y = +this.$parent.formA.sensorY || 0;
+            let z = +this.$parent.formA.sensorZ || 0;
+            let h = +this.$parent.formA.sensorP || 0;
+            let p = +this.$parent.formA.sensorR || 0;
+            let r = +this.$parent.formA.sensorH || 0;
+
+            this.initContent(
+                null,
+                { x, y, z },
+                {
+                    x: (-90 * Math.PI) / 180,
+                    y: 0,
+                    z: 0,
+                },
+                type
+            );
+
+            setTimeout(() => {
+                this.initSensor({ x, y, z }, type, true);
+
+                const obj = this.scene.getObjectByName("cube");
+
+                obj.position.x = x;
+                obj.position.y = y;
+                obj.position.z = z;
+
+                // obj.rotateX(0 * -1);
+                // obj.rotateX((h * Math.PI) / 180);
+                this.xAngle = ((h - 90) * Math.PI) / 180;
+
+                // obj.rotateY(0 * -1);
+                // obj.rotateY((p * Math.PI) / 180);
+                this.yAngle = (p * Math.PI) / 180;
+
+                // obj.rotateZ(0 * -1);
+                // obj.rotateZ((r * Math.PI) / 180);
+                this.zAngle = (r * Math.PI) / 180;
+                obj.rotation.set(this.xAngle, this.yAngle, this.zAngle);
+            }, 0);
+        },
+        // 初始化传感器
+        initSensor(
+            pos = { x: 0, y: 0, z: 0 },
+            type = "camera",
+            canMove = false
+        ) {
+            let Loader = new MTLLoader(); //材质文件加载器
+            let loader = new OBJLoader(); //obj加载器
+            let that = this;
+            let mtlUrl = "";
+            let objUrl = "";
+
+            if (type === "camera") {
+                mtlUrl = `${that.publicPath}sensor/camera/camera.mtl`;
+                objUrl = `${that.publicPath}sensor/camera/camera.obj`;
+            } else if (type === "ogt") {
+                mtlUrl = `${that.publicPath}sensor/ogt/millimeter_wave_radar.mtl`;
+                objUrl = `${that.publicPath}sensor/ogt/millimeter_wave_radar.obj`;
+            } else if (type === "lidar") {
+                mtlUrl = `${that.publicPath}sensor/lidar/LIDAR.mtl`;
+                objUrl = `${that.publicPath}sensor/lidar/LIDAR.obj`;
+            } else if (type === "gps") {
+                mtlUrl = `${that.publicPath}sensor/gps/lidar.mtl`;
+                objUrl = `${that.publicPath}sensor/gps/lidar.obj`;
+            }
+
+            let loading = null;
+            if (type === "ogt") {
+                // loading = this.$loading({
+                //     lock: true,
+                //     text: "模型加载中,请稍等...",
+                //     // spinner: "el-icon-loading",
+                //     background: "rgba(0, 0, 0, 0.2)",
+                // });
+                showFullScreenLoading();
+            }
+
+            Loader.load(
+                mtlUrl,
+                function (materials) {
+                    loader.setMaterials(materials);
+                    loader.load(objUrl, function (obj) {
+                        if (type === "ogt") {
+                            // loading.close();
+                            tryHideFullScreenLoading();
+                        }
+
+                        that.cacheList.push(obj);
+                        for (let i = 0; i < obj.children.length; i++) {
+                            if (type === "camera") {
+                                obj.children[i].scale.set(0.8, 0.8, 0.8);
+                            } else if (type === "ogt") {
+                                obj.children[i].scale.set(0.2, 0.2, 0.2);
+                            } else if (type === "lidar") {
+                                obj.children[i].scale.set(0.1, 0.1, 0.1);
+                            } else if (type === "gps") {
+                                obj.children[i].scale.set(40, 40, 40);
+                            }
+                        }
+                        obj.position.set(pos.x, pos.y, pos.z);
+
+                        if (canMove) {
+                            that.sensor = obj;
+                        }
+
+                        that.scene.add(obj); //返回的组对象插入场景中
+                    });
+                },
+                (xhr) => {
+                    // console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
+                },
+                (error) => {
+                    if (type === "ogt") {
+                        // loading.close();
+                        tryHideFullScreenLoading();
+                    }
+                    console.error(error);
+                }
+            );
+        },
+        // 初始化已保存过的传感器
+        initContentToShow(r, position, rotation, type) {
+            var cubeGeometry = new THREE.ConeGeometry(
+                r || 45 * this.scale,
+                150 * this.scale,
+                4,
+                1,
+                false
+            );
+            cubeGeometry.translate(0, -150, 0);
+
+            let obj = {
+                transparent: true,
+                opacity: 0.3,
+                lightMapIntensity: 0.1,
+                color: 0x4c4c4c,
+            };
+
+            if (type === "camera") {
+                obj.emissive = 0x000080;
+            } else if (type === "ogt") {
+                obj.emissive = 0x008000;
+            } else if (type === "lidar") {
+                obj.emissive = 0xff4500;
+            } else if (type === "gps") {
+                obj.emissive = 0x8a2be2;
+            }
+
+            var cubeMaterial = new THREE.MeshLambertMaterial(obj);
+
+            var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
+            cube.name = this.geometryName || "cubeA";
+            cube.rotateX((-90 * Math.PI) / 180);
+
+            if (position) {
+                cube.position.x = position.x;
+                cube.position.y = position.y;
+                cube.position.z = position.z;
+            }
+            if (rotation) {
+                cube.rotation.set(
+                    ((rotation.x - 90) * Math.PI) / 180,
+                    (rotation.y * Math.PI) / 180,
+                    (rotation.z * Math.PI) / 180
+                );
+            }
+            this.cacheList.push(cube);
+            this.scene.add(cube);
+        },
+        // 生成一种类型的全部显示器
+        showSensor(sensor, type) {
+            if (sensor && Array.isArray(sensor) && sensor.length > 0) {
+                sensor.forEach((item) => {
+                    this.initContentToShow(
+                        null,
+                        {
+                            x: Math.floor(item.sensorX / this.rate || 0),
+                            y: Math.floor(item.sensorY / this.rate || 0),
+                            z: Math.floor(item.sensorZ / this.rate || 0),
+                        },
+                        {
+                            x: +item.sensorP,
+                            y: +item.sensorR,
+                            z: +item.sensorH,
+                        },
+                        type
+                    );
+
+                    this.initSensor(
+                        {
+                            x: Math.floor(item.sensorX / this.rate || 0),
+                            y: Math.floor(item.sensorY / this.rate || 0),
+                            z: Math.floor(item.sensorZ / this.rate || 0),
+                        },
+                        type,
+                        false
+                    );
+                });
+            }
+        },
+        // 显示全部
+        showAll(configList) {
+            // 避免重复加载所有传感器
+            if (!this.canDrag) return;
+
+            this.canDrag = false;
+            if (this.cacheList.length > 0) {
+                this.scene.remove(...this.cacheList);
+                this.cacheList = [];
+            }
+
+            const obj = this.scene.getObjectByName("cube");
+            if (obj) {
+                this.scene.remove(obj);
+            }
+
+            if (this.dragControls) {
+                this.dragControls.deactivate();
+                this.dragControls.dispose();
+                this.dragControls = null;
+            }
+
+            if (this.transformControls) {
+                this.transformControls.detach();
+            }
+
+            this.showSensor(configList.camera, "camera");
+            this.showSensor(configList.ogt, "ogt");
+            this.showSensor(configList.lidar, "lidar");
+            this.showSensor(configList.gps, "gps");
+        },
+        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();
+        // console.log(showFullScreenLoading);
+    },
+    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.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>
+#containerThreeProjectInfo {
+    width: 100%;
+    height: calc(100vh - 125px);
+}
+</style>

+ 19 - 6
src/views/workManagement/projectInfo.vue

@@ -144,11 +144,15 @@
                             ></handle-config-list>
                         </div>
                         <div class="canvasBox">
-                            <canvas-sensor
+                            <!-- <canvas-sensor
                                 v-if="modelImgSrc"
                                 :modelImgSrc="modelImgSrc"
                                 :configList="configList"
-                            ></canvas-sensor>
+                            ></canvas-sensor> -->
+                            <three-show
+                                ref="threeShow"
+                                :carModel="carModel"
+                            ></three-show>
                         </div>
                     </div>
                 </div>
@@ -216,7 +220,8 @@
 import handleConfigList from "../modelLibrary/components/handleConfigList.vue";
 import tableList from "@/components/grid/TableList";
 import pieChartProjectInfo from "@/components/echarts/pieChartProjectInfo";
-import canvasSensor from "./components/canvasProjectInfo.vue";
+// import canvasSensor from "./components/canvasProjectInfo.vue";
+import threeShow from "./components/threeProjectInfo.vue";
 import { mapState } from "vuex";
 
 export default {
@@ -225,7 +230,8 @@ export default {
         handleConfigList,
         tableList,
         pieChartProjectInfo,
-        canvasSensor,
+        // canvasSensor,
+        threeShow,
     },
     data() {
         return {
@@ -331,7 +337,8 @@ export default {
             },
             downImgSrc: require("@/assets/common/image/others/noDoc.png"),
             // modelImgSrc: require("@/assets/common/image/others/carTopView.png"), // 车辆图片地址
-            modelImgSrc: "", // 车辆图片地址
+            // modelImgSrc: "", // 车辆图片地址
+            carModel: "",
             stateList: [], // 任务运行状态统计数据
             resultList: [],
         };
@@ -453,7 +460,13 @@ export default {
                     this.configList.lidar = res.info.sensorLidarList || [];
                     this.configList.gps = res.info.sensorGpsList || [];
 
-                    this.modelImgSrc = this.getImgUrl(res.info.vehicleTopView);
+                    // this.modelImgSrc = this.getImgUrl(res.info.vehicleTopView);
+                    // this.carModel = this.getImgUrl(res.info.vehicleFrontView);
+                    this.carModel = this.getImgUrl(res.info.vehicleTopView);
+                    // this.carModel = this.getImgUrl('/vehicleImg/20221019/1666158952428/AudiA6_10.glb');
+
+                    if (this.$refs.threeShow)
+                        this.$refs.threeShow.showAll(this.configList);
 
                     if (this.info.nowRunState === "30") {
                         this.downImgSrc = require("@/assets/common/image/others/hasDoc.png");