Browse Source

* 主路光伏,卡顿

chen.cheng 1 month ago
parent
commit
7590e9bd71

BIN
ems-ui-cloud/public/models/model-road-pv.glb


+ 2 - 2
ems-ui-cloud/src/views/largeScreen/pv-road/center.vue

@@ -37,9 +37,9 @@ export default {
           props: {
             areaCode: "321283124S3003"
           }
-        }), "北区光伏", {
+        }), "主路光伏", {
           x: 0,
-          y: 20,
+          y: 0,
           z: 20
         })
       }, 100)

+ 117 - 120
ems-ui-cloud/src/views/largeScreen/three/renderModel.js

@@ -34,56 +34,88 @@ class renderModel {
     //模型平面
     this.planeGeometry;
 
-    this.outlineObjs = []
+    this.outlineObjs = [];
+    this.sharedComposer = null;
+    this.sharedOutlinePass = null;
+    this.sharedBloomPass = null;
+    this.isComposerInitialized = false;
+    this.raycaster = new THREE.Raycaster();
+    this.mouse = new THREE.Vector2();
   }
 
-  outlineObj(selectedObjects) {
-    // 创建一个EffectComposer(效果组合器)对象,然后在该对象上添加后期处理通道。
-    // 用于模型边缘高亮
-    let composer = new EffectComposer(this.renderer);
-    composer.renderTarget1.texture.outputColorSpace = THREE.sRGBEncoding;
-    composer.renderTarget2.texture.outputColorSpace = THREE.sRGBEncoding;
-    composer.renderTarget1.texture.encoding = THREE.sRGBEncoding;
-    composer.renderTarget2.texture.encoding = THREE.sRGBEncoding;
-
-    // 新建一个场景通道  为了覆盖到原来的场景上
-    composer.addPass(new RenderPass(this.scene, this.camera));
-    // 物体边缘发光通道
-    let outlinePass = new OutlinePass(
+  // 初始化共享后处理系统
+  initSharedPostProcessing() {
+    if (this.isComposerInitialized) return;
+
+    // 创建共享的EffectComposer
+    this.sharedComposer = new EffectComposer(this.renderer);
+    this.sharedComposer.renderTarget1.texture.outputColorSpace = THREE.sRGBEncoding;
+    this.sharedComposer.renderTarget2.texture.outputColorSpace = THREE.sRGBEncoding;
+    this.sharedComposer.renderTarget1.texture.encoding = THREE.sRGBEncoding;
+    this.sharedComposer.renderTarget2.texture.encoding = THREE.sRGBEncoding;
+
+    // 添加基础渲染通道
+    const renderPass = new RenderPass(this.scene, this.camera);
+    this.sharedComposer.addPass(renderPass);
+
+    // 创建共享的OutlinePass
+    this.sharedOutlinePass = new OutlinePass(
       new THREE.Vector2(window.innerWidth, window.innerHeight),
       this.scene,
-      this.camera,
-      selectedObjects
+      this.camera
     );
-    outlinePass.selectedObjects = selectedObjects;
-    outlinePass.edgeStrength = 10.0; // 边框的亮度
-    outlinePass.edgeGlow = 0.5; // 光晕[0,1]
-    outlinePass.usePatternTexture = false; // 是否使用父级的材质
-    outlinePass.edgeThickness = 1.0; // 边框宽度
-    outlinePass.downSampleRatio = 1; // 边框弯曲度
-    outlinePass.pulsePeriod = 5; // 呼吸闪烁的速度
-    outlinePass.visibleEdgeColor.set(parseInt(0x00ff00)); // 呼吸显示的颜色
-    outlinePass.hiddenEdgeColor = new THREE.Color(0, 0, 0); // 呼吸消失的颜色
-    outlinePass.clear = true;
-    composer.addPass(outlinePass);
-    // 自定义的着色器通道 作为参数
-    // effectFXAA = new ShaderPass(FXAAShader);
-    // effectFXAA.uniforms.resolution.value.set(
-    //   1 / window.innerWidth,
-    //   1 / window.innerHeight
-    // );
-    // effectFXAA.renderToScreen = true;
-    // composer.addPass(effectFXAA);
-
-    // // 发光效果
-    let unrealBloomPass = new UnrealBloomPass();
-    unrealBloomPass.strength = 0.1;
-    unrealBloomPass.radius = 0;
-    unrealBloomPass.threshold = 1;
-    composer.addPass(unrealBloomPass);
-    this.outlineObjs.push(composer)
-    console.log(">>>>>>>>>>>>>>>>>>>>>")
+    // 设置轮廓效果参数
+    this.sharedOutlinePass.edgeStrength = 5.0; // 边框的亮度
+    this.sharedOutlinePass.edgeGlow = 0.3; // 光晕[0,1]
+    this.sharedOutlinePass.edgeThickness = 1.0; // 边框宽度
+    this.sharedOutlinePass.pulsePeriod = 3; // 呼吸闪烁的速度
+    this.sharedOutlinePass.visibleEdgeColor.set(0x00ff00); // 呼吸显示的颜色
+    this.sharedOutlinePass.hiddenEdgeColor.set(0x000000); // 呼吸消失的颜色
+    this.sharedOutlinePass.clear = true;
+    this.sharedComposer.addPass(this.sharedOutlinePass);
+
+    // 创建共享的UnrealBloomPass
+    this.sharedBloomPass = new UnrealBloomPass();
+    this.sharedBloomPass.strength = 0.1;
+    this.sharedBloomPass.radius = 0;
+    this.sharedBloomPass.threshold = 1;
+    this.sharedComposer.addPass(this.sharedBloomPass);
+
+    this.isComposerInitialized = true;
+
+    // 监听窗口大小变化,更新后处理分辨率
+    window.addEventListener('resize', () => {
+      if (this.sharedOutlinePass) {
+        this.sharedOutlinePass.resolution.set(window.innerWidth, window.innerHeight);
+      }
+    });
+  }
+
+  // 优化后的模型高亮方法
+  outlineObj(selectedObjects) {
+    // 初始化共享后处理系统
+    this.initSharedPostProcessing();
 
+    // 更新选中对象
+    if (this.sharedOutlinePass) {
+      this.sharedOutlinePass.selectedObjects = selectedObjects;
+
+      // 如果之前有高亮对象,先清除
+      if (this.outlineObjs.length > 0) {
+        this.outlineObjs = [];
+      }
+
+      // 添加当前共享的composer到数组
+      this.outlineObjs.push(this.sharedComposer);
+    }
+  }
+
+  // 清理高亮效果
+  clearHighlight() {
+    if (this.sharedOutlinePass) {
+      this.sharedOutlinePass.selectedObjects = [];
+      this.outlineObjs = [];
+    }
   }
 
   // 初始化加载模型方法
@@ -100,13 +132,14 @@ class renderModel {
     this.initControls();
     this.setFBXModel();
     //监听场景大小改变,跳转渲染尺寸
-    window.addEventListener('resize', this.onWindowResizes);
+    window.addEventListener('resize', this.onWindowResizes.bind(this));
     //场景渲染
     this.sceneAnimation();
+    // 添加鼠标点击事件
+    window.addEventListener('click', this.onMouseClick.bind(this));
   }
 
   initGltfModel() {
-
     //初始化场景
     this.initScene();
     //初始化相机
@@ -119,9 +152,32 @@ class renderModel {
     this.initControls();
     this.setGlbModel();
     //监听场景大小改变,跳转渲染尺寸
-    window.addEventListener('resize', this.onWindowResizes);
+    window.addEventListener('resize', this.onWindowResizes.bind(this));
     //场景渲染
     this.sceneAnimation();
+    // 添加鼠标点击事件
+    window.addEventListener('click', this.onMouseClick.bind(this));
+  }
+
+  onMouseClick(event) {
+    // 计算鼠标在标准化设备坐标中的位置 (-1 to +1)
+    this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
+    this.mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
+
+    // 更新射线
+    this.raycaster.setFromCamera(this.mouse, this.camera);
+
+    // 计算射线与场景中物体的交点
+    const intersects = this.raycaster.intersectObjects(this.scene.children, true);
+
+    if (intersects.length > 0) {
+      const point = intersects[0].point;
+      const object = intersects[0].object;
+      console.log(`Clicked on object: ${object.name} at (${point.x}, ${point.y}, ${point.z})`);
+
+      // 示例:点击时高亮对象
+      // this.outlineObj([object]);
+    }
   }
 
   //创建场景
@@ -220,15 +276,11 @@ class renderModel {
     this.controls.update();
     this.css3DRenderer.render(this.scene, this.camera);
     TWEEN.update();
-    // this.outlineObjs.forEach(item => {
-    //   item.render(this.scene, this.camera)
-    // })
-    // // 检查模型位置是否发生变化
-    // if (this.model) {
-    //   console.log('Model Position:', this.model.position);
-    //   console.log('Camera Position:', this.camera.position);
-    //   console.log('Controls Target:', this.controls.target);
-    // }
+
+    // 使用共享的composer进行后处理渲染
+    if (this.isComposerInitialized && this.sharedComposer) {
+      this.sharedComposer.render();
+    }
   }
 
   // 使用动画器不断更新场景
@@ -314,12 +366,17 @@ class renderModel {
     fbxLoader.load('/models/model-road-pv.glb', object => {
       this.calcMeshCenter(object.scene);
       this.model = object.scene;
+      const selectedObjects = [];
       object.scene.traverse(function (child) {
         if (child.isMesh) {
           child.material.emissive = child.material.color;
           child.material.emissiveMap = child.material.map;
         }
+        if (["solar_cell097001", "solar_cell097002", "solar_cell097003", "solar_cell097004"].includes(child.name)) {
+          selectedObjects.push(child);
+        }
       });
+
       // 设置相机位置
       this.camera.position.set(-20, -652, 500);
       this.controls.target.set(-20, -20, 0);
@@ -328,39 +385,10 @@ class renderModel {
       this.camera.lookAt(0, 0, 0);
       // 将模型添加到场景中去
       this.scene.add(this.model);
-      if (object.scene.type === 'Group') {
-        console.log('这是一个Group');
-        // 遍历Group中的子对象
-        object.scene.children.forEach(child => {
-          if (child.type === 'Mesh') {
-            console.log('这是一个Mesh', child.name); // 检查并记录Mesh的名称
-            if (["solar_cell097.001", "solar_cell097.002", "solar_cell097.003", "solar_cell097.004","Line007"].includes(child.name)) {
-              let selectedObjects = [child];
-              // this.outlineObj(selectedObjects);
-            }
-          }
-        });
-      } else if (object.scene.type === 'Mesh') {
-        console.log('这是一个单独的Mesh', object.scene.name); // 单独的Mesh对象
-      } else {
-        console.log('未知类型的对象', object.scene.type);
+       // 高亮收集的对象
+      if (selectedObjects.length > 0) {
+        this.outlineObj(selectedObjects);
       }
-      window.addEventListener('click', event => {
-
-        //   raycaster.setFromCamera(mouse, this.camera);
-
-        //   const intersects = raycaster.intersectObjects(this.scene.children);
-
-        const intersects = this.raycaster.intersectObjects(this.scene.children);
-
-        if (intersects.length > 0) {
-          const point = intersects[0].point;
-          console.log(`Clicked at: (${point.x}, ${point.y}, ${point.z})`);
-        }
-      });
-      console.log('load')
-      // this.initGUI();
-
     });
   }
 
@@ -383,37 +411,6 @@ class renderModel {
       this.camera.lookAt(0, 0, 0);
       // 将模型添加到场景中去
       this.scene.add(this.model);
-      if (object.type === 'Group') {
-        console.log('这是一个Group');
-        // 遍历Group中的子对象
-        object.children.forEach(child => {
-          if (child.type === 'Mesh') {
-            console.log('这是一个Mesh', child.name); // 检查并记录Mesh的名称
-            if (child.name === 'Line007') {
-              let selectedObjects = [child];
-              this.outlineObj(selectedObjects);
-            }
-          }
-        });
-      } else if (object.type === 'Mesh') {
-        console.log('这是一个单独的Mesh', object.name); // 单独的Mesh对象
-      } else {
-        console.log('未知类型的对象', object.type);
-      }
-      window.addEventListener('click', event => {
-
-        //   raycaster.setFromCamera(mouse, this.camera);
-
-        //   const intersects = raycaster.intersectObjects(this.scene.children);
-
-        const intersects = this.raycaster.intersectObjects(this.scene.children);
-
-        if (intersects.length > 0) {
-          const point = intersects[0].point;
-          console.log(`Clicked at: (${point.x}, ${point.y}, ${point.z})`);
-        }
-      });
-
     });
   }
 
@@ -424,6 +421,7 @@ class renderModel {
     this.camera.aspect = clientWidth / clientHeight; // 摄像机宽高比例
     this.camera.updateProjectionMatrix(); //相机更新矩阵,将3d内容投射到2d面上转换
     this.renderer.setSize(clientWidth, clientHeight);
+    this.css3DRenderer.setSize(clientWidth, clientHeight);
   }
 
   calcMeshCenter(group) {
@@ -443,7 +441,6 @@ class renderModel {
     group.position.z = 17;
   }
 
-
   addDialog(html, labelName, position) {
     const {x, y, z} = position
     const label3D = this.tag3D(labelName);